├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md ├── labeler.yml └── workflows │ ├── beepCD.yml │ ├── beepCI.yml │ ├── labeler.yml │ └── reviewKtlint.yml ├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── lighthouse │ ├── BeepApplication.kt │ ├── di │ ├── DataModule.kt │ ├── DatabaseModule.kt │ ├── HTTPRequestInterceptor.kt │ ├── NetworkModule.kt │ ├── ProviderModule.kt │ └── WorkManagerInitializer.kt │ └── utils │ └── log │ ├── ComponentLogger.kt │ └── CustomTimberTree.kt ├── build-logic ├── .gitignore ├── convention │ ├── .gitignore │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ ├── AndroidApplicationComposeConventionPlugin.kt │ │ ├── AndroidApplicationConventionPlugin.kt │ │ ├── AndroidHiltConventionPlugin.kt │ │ ├── AndroidLibraryComposeConventionPlugin.kt │ │ ├── AndroidLibraryConventionPlugin.kt │ │ ├── JavaLibraryConventionPlugin.kt │ │ └── com │ │ └── lighthouse │ │ └── convention │ │ ├── AndroidCompose.kt │ │ ├── DependencyHandlerExt.kt │ │ ├── KotlinAndroid.kt │ │ ├── ProjectConfigurations.kt │ │ └── ProjectExt.kt └── settings.gradle.kts ├── build.gradle.kts ├── data ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── com │ │ └── lighthouse │ │ ├── database │ │ ├── BeepDatabase.kt │ │ ├── converter │ │ │ ├── DateConverter.kt │ │ │ ├── DmsConverter.kt │ │ │ ├── RectConverter.kt │ │ │ └── UriConverter.kt │ │ ├── dao │ │ │ ├── BrandWithSectionDao.kt │ │ │ └── GifticonDao.kt │ │ ├── entity │ │ │ ├── BrandLocationEntity.kt │ │ │ ├── BrandWithSections.kt │ │ │ ├── GifticonCropEntity.kt │ │ │ ├── GifticonEntity.kt │ │ │ ├── GifticonWithCrop.kt │ │ │ ├── HistoryEntity.kt │ │ │ └── SectionEntity.kt │ │ └── mapper │ │ │ ├── GifticonCropEntityMapper.kt │ │ │ ├── GifticonForAddtionMapper.kt │ │ │ ├── GifticonForUpdateMapper.kt │ │ │ ├── GifticonWithCropMapper.kt │ │ │ └── HistoryMapper.kt │ │ ├── datasource │ │ ├── auth │ │ │ ├── AuthDataSource.kt │ │ │ └── AuthDataSourceImpl.kt │ │ ├── brand │ │ │ ├── BrandLocalDataSource.kt │ │ │ ├── BrandLocalDataSourceImpl.kt │ │ │ ├── BrandRemoteDataSource.kt │ │ │ └── BrandRemoteDataSourceImpl.kt │ │ ├── gallery │ │ │ ├── GalleryImageLocalSource.kt │ │ │ ├── GalleryImageLocalSourceImpl.kt │ │ │ └── GalleryImagePagingSource.kt │ │ ├── gifticon │ │ │ ├── GifticonImageRecognizeSource.kt │ │ │ ├── GifticonImageSource.kt │ │ │ ├── GifticonLocalDataSource.kt │ │ │ └── GifticonLocalDataSourceImpl.kt │ │ └── location │ │ │ └── SharedLocationManager.kt │ │ ├── mapper │ │ ├── BrandEntityMapper.kt │ │ ├── BrandPlaceInfoDataContainerMapper.kt │ │ ├── ErrorMapper.kt │ │ ├── GifticonCropMapper.kt │ │ ├── GifticonEntityMapper.kt │ │ ├── GifticonRecognizeInfoMapper.kt │ │ ├── RectMapper.kt │ │ └── RectangleMapper.kt │ │ ├── model │ │ ├── BeepErrorData.kt │ │ ├── BrandPlaceInfoDataContainer.kt │ │ └── GifticonImageResult.kt │ │ ├── network │ │ └── NetworkApiService.kt │ │ ├── repository │ │ ├── AuthRepositoryImpl.kt │ │ ├── BrandRepositoryImpl.kt │ │ ├── GalleryImageRepositoryImpl.kt │ │ ├── GifticonImageRecognizeRepositoryImpl.kt │ │ ├── GifticonRepositoryImpl.kt │ │ ├── LocationRepositoryImpl.kt │ │ ├── SecurityRepositoryImpl.kt │ │ └── UserPreferencesRepositoryImpl.kt │ │ └── util │ │ ├── CryptoObjectHelper.kt │ │ ├── UUID.kt │ │ └── recognizer │ │ ├── BalanceRecognizer.kt │ │ ├── BarcodeRecognizer.kt │ │ ├── ExpiredRecognizer.kt │ │ ├── GifticonRecognizeInfo.kt │ │ ├── GifticonRecognizer.kt │ │ ├── TextRecognizer.kt │ │ ├── parser │ │ ├── BalanceParser.kt │ │ ├── BalanceParserResult.kt │ │ ├── BarcodeParser.kt │ │ ├── BarcodeParserResult.kt │ │ ├── BaseParser.kt │ │ ├── CashCardRegex.kt │ │ ├── ExpiredParser.kt │ │ └── ExpiredParserResult.kt │ │ ├── processor │ │ ├── BaseProcessor.kt │ │ ├── GifticonProcessImage.kt │ │ ├── GifticonProcessResult.kt │ │ ├── GifticonProcessText.kt │ │ ├── GifticonProcessTextTag.kt │ │ └── ScaleProcessor.kt │ │ └── recognizer │ │ ├── TemplateRecognizer.kt │ │ ├── giftishow │ │ ├── GiftishowParser.kt │ │ ├── GiftishowProcessor.kt │ │ └── GiftishowRecognizer.kt │ │ ├── kakao │ │ ├── KakaoParser.kt │ │ ├── KakaoProcessor.kt │ │ └── KakaoRecognizer.kt │ │ ├── smilecon │ │ ├── SmileConParser.kt │ │ ├── SmileConProcessor.kt │ │ └── SmileConRecognizer.kt │ │ └── syrup │ │ ├── SyrupParser.kt │ │ ├── SyrupProcessor.kt │ │ └── SyrupRecognizer.kt │ └── test │ └── java │ └── data │ └── datasource │ └── BrandLocalDataSourceTest.kt ├── domain ├── .gitignore ├── build.gradle.kts └── src │ ├── main │ └── java │ │ └── com │ │ └── lighthouse │ │ └── domain │ │ ├── LocationConverter.kt │ │ ├── model │ │ ├── BeepError.kt │ │ ├── Brand.kt │ │ ├── BrandPlaceInfo.kt │ │ ├── DbResult.kt │ │ ├── GalleryImage.kt │ │ ├── Gifticon.kt │ │ ├── GifticonCrop.kt │ │ ├── GifticonForAddition.kt │ │ ├── GifticonForUpdate.kt │ │ ├── History.kt │ │ ├── Rectangle.kt │ │ ├── SortBy.kt │ │ └── UserPreferenceOption.kt │ │ ├── repository │ │ ├── AuthRepository.kt │ │ ├── BrandRepository.kt │ │ ├── GalleryImageRepository.kt │ │ ├── GifticonImageRecognizeRepository.kt │ │ ├── GifticonRepository.kt │ │ ├── LocationRepository.kt │ │ ├── SecurityRepository.kt │ │ └── UserPreferencesRepository.kt │ │ ├── usecase │ │ ├── GetAllBrandsUseCase.kt │ │ ├── GetBrandPlaceInfosUseCase.kt │ │ ├── GetFilteredGifticonsUseCase.kt │ │ ├── GetFingerprintCipherUseCase.kt │ │ ├── GetGifticonUseCase.kt │ │ ├── GetGifticonsUseCase.kt │ │ ├── GetHistoryUseCase.kt │ │ ├── GetSharedDateUseCase.kt │ │ ├── GetUserLocationUseCase.kt │ │ ├── HasVariableGifticonUseCase.kt │ │ ├── MoveUserIdGifticonUseCase.kt │ │ ├── RemoveExpirationBrandUseCase.kt │ │ ├── RemoveGifticonUseCase.kt │ │ ├── ResetHistoryButInitUseCase.kt │ │ ├── UnUseGifticonUseCase.kt │ │ ├── UpdateSharedDateUseCase.kt │ │ ├── UseCashCardGifticonUseCase.kt │ │ ├── UseGifticonUseCase.kt │ │ ├── edit │ │ │ ├── HasGifticonBrandUseCase.kt │ │ │ ├── RecognizeBalanceUseCase.kt │ │ │ ├── RecognizeBarcodeUseCase.kt │ │ │ ├── RecognizeBrandNameUseCase.kt │ │ │ ├── RecognizeExpiredUseCase.kt │ │ │ ├── RecognizeGifticonImageUseCase.kt │ │ │ ├── RecognizeGifticonNameUseCase.kt │ │ │ ├── addgifticon │ │ │ │ ├── AddRecognizeUseCase.kt │ │ │ │ └── SaveGifticonsUseCase.kt │ │ │ └── modifygifticon │ │ │ │ ├── GetGifticonForUpdateUseCase.kt │ │ │ │ ├── ModifyGifticonUseCase.kt │ │ │ │ └── ModifyRecognizeUseCase.kt │ │ ├── gallery │ │ │ └── GetGalleryImagesUseCase.kt │ │ └── setting │ │ │ ├── GetCorrespondWithPinUseCase.kt │ │ │ ├── GetGuestOptionUseCase.kt │ │ │ ├── GetNotificationOptionUseCase.kt │ │ │ ├── GetOptionStoredUseCase.kt │ │ │ ├── GetSecurityOptionUseCase.kt │ │ │ ├── MoveGuestDataUseCase.kt │ │ │ ├── RemoveUserDataUseCase.kt │ │ │ ├── SaveGuestOptionUseCase.kt │ │ │ ├── SaveNotificationOptionUseCase.kt │ │ │ ├── SavePinUseCase.kt │ │ │ └── SaveSecurityOptionUseCase.kt │ │ └── util │ │ └── DateTime.kt │ └── test │ └── java │ └── com │ └── lighthouse │ └── domain │ └── usecase │ └── GetBrandPlaceInfosUseCaseTest.kt ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── presentation ├── .gitignore ├── build.gradle.kts ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── lighthouse │ │ │ └── presentation │ │ │ ├── adapter │ │ │ ├── BindableAdapter.kt │ │ │ ├── BindableListAdapter.kt │ │ │ └── BindablePagingAdapter.kt │ │ │ ├── background │ │ │ ├── BeepWorkManager.kt │ │ │ ├── ExpirationBrandWorker.kt │ │ │ ├── NotificationHelper.kt │ │ │ └── NotificationWorker.kt │ │ │ ├── binding │ │ │ ├── ImageView.kt │ │ │ ├── Layout.kt │ │ │ ├── RecyclerView.kt │ │ │ ├── TextInputLayout.kt │ │ │ ├── TextView.kt │ │ │ └── View.kt │ │ │ ├── extension │ │ │ ├── Bitmap.kt │ │ │ ├── Bundle.kt │ │ │ ├── ContentResolver.kt │ │ │ ├── Date.kt │ │ │ ├── DialogFragment.kt │ │ │ ├── Intent.kt │ │ │ ├── KotlinExtention.kt │ │ │ ├── LifecycleOwner.kt │ │ │ ├── ScrollView.kt │ │ │ └── View.kt │ │ │ ├── extra │ │ │ └── Extras.kt │ │ │ ├── mapper │ │ │ ├── AddGifticonUIModelMapper.kt │ │ │ ├── BrandPlaceInfoUiModelMapper.kt │ │ │ ├── GalleryImageMapper.kt │ │ │ ├── GalleryUIModelMapper.kt │ │ │ ├── GifticonForAdditionMapper.kt │ │ │ ├── GifticonForUpdateMapper.kt │ │ │ ├── GifticonMapper.kt │ │ │ ├── GifticonSortByMapper.kt │ │ │ ├── HistoryMapper.kt │ │ │ ├── ModifyGifticonUIModelMapper.kt │ │ │ ├── RectMapper.kt │ │ │ └── RectangleMapper.kt │ │ │ ├── model │ │ │ ├── AddGifticonUIModel.kt │ │ │ ├── BrandPlaceInfoUiModel.kt │ │ │ ├── CashAmountPreset.kt │ │ │ ├── CroppedImage.kt │ │ │ ├── GalleryUIModel.kt │ │ │ ├── GifticonSortBy.kt │ │ │ ├── GifticonUIModel.kt │ │ │ ├── GifticonWithDistanceUIModel.kt │ │ │ ├── HistoryUiModel.kt │ │ │ ├── LocationUiModel.kt │ │ │ └── ModifyGifticonUIModel.kt │ │ │ ├── ui │ │ │ ├── common │ │ │ │ ├── ConcurrencyTextField.kt │ │ │ │ ├── FragmentViewBindingDelegate.kt │ │ │ │ ├── GifticonViewHolderType.kt │ │ │ │ ├── UiState.kt │ │ │ │ ├── VerticalTextView.kt │ │ │ │ ├── compose │ │ │ │ │ ├── ConcurrencyTextField.kt │ │ │ │ │ └── TextCheckbox.kt │ │ │ │ ├── dialog │ │ │ │ │ ├── ConfirmationDialog.kt │ │ │ │ │ ├── OriginImageDialog.kt │ │ │ │ │ ├── ProgressDialog.kt │ │ │ │ │ └── datepicker │ │ │ │ │ │ ├── OnDatePickListener.kt │ │ │ │ │ │ ├── SpinnerDatePicker.kt │ │ │ │ │ │ └── SpinnerDatePickerViewModel.kt │ │ │ │ └── view │ │ │ │ │ ├── BalanceTextInputEditText.kt │ │ │ │ │ ├── BarcodeTextInputEditText.kt │ │ │ │ │ ├── FormattedTextInputEditText.kt │ │ │ │ │ ├── RealValueLengthFilter.kt │ │ │ │ │ └── ScrollableTextView.kt │ │ │ ├── cropgifticon │ │ │ │ ├── CropGifticonActivity.kt │ │ │ │ ├── CropGifticonParams.kt │ │ │ │ ├── CropGifticonViewModel.kt │ │ │ │ ├── event │ │ │ │ │ └── CropGifticonEvent.kt │ │ │ │ └── view │ │ │ │ │ ├── CropImageInfo.kt │ │ │ │ │ ├── CropImageMode.kt │ │ │ │ │ ├── CropImagePen.kt │ │ │ │ │ ├── CropImageView.kt │ │ │ │ │ ├── CropImageWindow.kt │ │ │ │ │ ├── OnChangeCropRectListener.kt │ │ │ │ │ ├── OnCropImageListener.kt │ │ │ │ │ ├── OnCropImagePenListener.kt │ │ │ │ │ └── OnCropImageWindowListener.kt │ │ │ ├── detailgifticon │ │ │ │ ├── CashCardGifticonInfoFragment.kt │ │ │ │ ├── GifticonDetailActivity.kt │ │ │ │ ├── GifticonDetailEvent.kt │ │ │ │ ├── GifticonDetailMode.kt │ │ │ │ ├── GifticonDetailViewModel.kt │ │ │ │ ├── StandardGifticonInfoFragment.kt │ │ │ │ └── dialog │ │ │ │ │ ├── LargeBarcodeDialog.kt │ │ │ │ │ └── UseGifticonDialog.kt │ │ │ ├── edit │ │ │ │ ├── addgifticon │ │ │ │ │ ├── AddGifticonActivity.kt │ │ │ │ │ ├── AddGifticonViewModel.kt │ │ │ │ │ ├── adapter │ │ │ │ │ │ ├── AddCandidateGifticonDisplayModel.kt │ │ │ │ │ │ ├── AddCandidateGifticonViewHolder.kt │ │ │ │ │ │ ├── AddGifticonAdapter.kt │ │ │ │ │ │ ├── AddGifticonItemUIModel.kt │ │ │ │ │ │ └── AddGotoGalleryViewHolder.kt │ │ │ │ │ └── event │ │ │ │ │ │ ├── AddGifticonCrop.kt │ │ │ │ │ │ ├── AddGifticonEvent.kt │ │ │ │ │ │ ├── AddGifticonTag.kt │ │ │ │ │ │ └── AddGifticonValid.kt │ │ │ │ └── modifygifticon │ │ │ │ │ ├── ModifyGifticonActivity.kt │ │ │ │ │ ├── ModifyGifticonViewModel.kt │ │ │ │ │ └── event │ │ │ │ │ ├── ModifyGifticonCrop.kt │ │ │ │ │ ├── ModifyGifticonEvent.kt │ │ │ │ │ ├── ModifyGifticonTag.kt │ │ │ │ │ └── ModifyGifticonValid.kt │ │ │ ├── gallery │ │ │ │ ├── GalleryActivity.kt │ │ │ │ ├── GalleryViewModel.kt │ │ │ │ ├── adapter │ │ │ │ │ ├── GallerySelection.kt │ │ │ │ │ ├── list │ │ │ │ │ │ ├── GalleryAdapter.kt │ │ │ │ │ │ ├── GalleryDisplayModel.kt │ │ │ │ │ │ ├── GalleryHeaderViewHolder.kt │ │ │ │ │ │ └── GalleryItemViewHolder.kt │ │ │ │ │ └── selected │ │ │ │ │ │ ├── SelectedGalleryAdapter.kt │ │ │ │ │ │ ├── SelectedGalleryDisplayModel.kt │ │ │ │ │ │ └── SelectedGalleryItemViewHolder.kt │ │ │ │ └── event │ │ │ │ │ └── GalleryEvent.kt │ │ │ ├── gifticonlist │ │ │ │ ├── GifticonListFragment.kt │ │ │ │ ├── GifticonListViewModel.kt │ │ │ │ ├── GifticonListViewState.kt │ │ │ │ └── component │ │ │ │ │ ├── BrandChip.kt │ │ │ │ │ ├── GifticonList.kt │ │ │ │ │ ├── GifticonListScreen.kt │ │ │ │ │ ├── GifticonListToolBar.kt │ │ │ │ │ └── Preview.kt │ │ │ ├── history │ │ │ │ ├── HistoryBottomSheet.kt │ │ │ │ ├── HistoryItemDecoration.kt │ │ │ │ └── adapter │ │ │ │ │ └── gifticondetail │ │ │ │ │ ├── HistoryAdapter.kt │ │ │ │ │ ├── HistoryHeaderViewHolder.kt │ │ │ │ │ └── HistoryItemViewHolder.kt │ │ │ ├── home │ │ │ │ ├── HomeEmptyFragment.kt │ │ │ │ ├── HomeEvent.kt │ │ │ │ ├── HomeFragment.kt │ │ │ │ ├── HomeFragmentContainer.kt │ │ │ │ ├── HomeViewModel.kt │ │ │ │ └── adapter │ │ │ │ │ ├── NearGifticonAdapter.kt │ │ │ │ │ └── NearGifticonDisplayModel.kt │ │ │ ├── main │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── MainEvent.kt │ │ │ │ ├── MainPage.kt │ │ │ │ └── MainViewModel.kt │ │ │ ├── map │ │ │ │ ├── MapActivity.kt │ │ │ │ ├── MapEvent.kt │ │ │ │ ├── MapViewModel.kt │ │ │ │ ├── OnLocationUpdateListener.kt │ │ │ │ └── adapter │ │ │ │ │ └── GifticonAdapter.kt │ │ │ ├── security │ │ │ │ ├── AuthCallback.kt │ │ │ │ ├── AuthManager.kt │ │ │ │ ├── CheckLocationFragment.kt │ │ │ │ ├── SecurityActivity.kt │ │ │ │ ├── SecurityViewModel.kt │ │ │ │ ├── event │ │ │ │ │ └── SecurityDirections.kt │ │ │ │ ├── fingerprint │ │ │ │ │ ├── FingerprintFragment.kt │ │ │ │ │ └── biometric │ │ │ │ │ │ └── BiometricAuth.kt │ │ │ │ └── pin │ │ │ │ │ ├── PinDialog.kt │ │ │ │ │ ├── PinDialogViewModel.kt │ │ │ │ │ ├── PinFragment.kt │ │ │ │ │ ├── PinSettingType.kt │ │ │ │ │ ├── PinSettingViewModel.kt │ │ │ │ │ └── PinViewModel.kt │ │ │ ├── setting │ │ │ │ ├── SecurityOption.kt │ │ │ │ ├── SettingFragment.kt │ │ │ │ ├── SettingMainFragment.kt │ │ │ │ ├── SettingSecurityFragment.kt │ │ │ │ ├── SettingViewModel.kt │ │ │ │ ├── UsedGifticonFragment.kt │ │ │ │ ├── UsedGifticonViewModel.kt │ │ │ │ └── UserPreferenceState.kt │ │ │ ├── signin │ │ │ │ ├── SignInActivity.kt │ │ │ │ ├── SignInFragment.kt │ │ │ │ └── SignInViewModel.kt │ │ │ └── widget │ │ │ │ ├── BeepWidget.kt │ │ │ │ ├── BeepWidgetInfoStateDefinition.kt │ │ │ │ ├── BeepWidgetReceiver.kt │ │ │ │ ├── BeepWidgetWorker.kt │ │ │ │ ├── WidgetState.kt │ │ │ │ └── component │ │ │ │ └── GlanceKtx.kt │ │ │ └── util │ │ │ ├── BarcodeUtil.kt │ │ │ ├── Geography.kt │ │ │ ├── OnThrottleClickListener.kt │ │ │ ├── TimeCalculator.kt │ │ │ ├── UUID.kt │ │ │ ├── flow │ │ │ ├── Combine.kt │ │ │ └── EventFlow.kt │ │ │ ├── parser │ │ │ ├── BaseParser.kt │ │ │ ├── CConParser.kt │ │ │ ├── DefaultParser.kt │ │ │ ├── GifticonParser.kt │ │ │ ├── GiftishowParser.kt │ │ │ ├── KakaoParser.kt │ │ │ └── SyrupParser.kt │ │ │ ├── permission │ │ │ ├── LocationPermissionManager.kt │ │ │ ├── StoragePermissionManager.kt │ │ │ └── core │ │ │ │ ├── ActivityPermissionDelegate.kt │ │ │ │ ├── BeepPermissionState.kt │ │ │ │ ├── FragmentPermissionDelegate.kt │ │ │ │ ├── PermissionDelegate.kt │ │ │ │ ├── PermissionFactory.kt │ │ │ │ └── PermissionManager.kt │ │ │ ├── recycler │ │ │ ├── GridSectionSpaceItemDecoration.kt │ │ │ ├── GridSpaceItemDecoration.kt │ │ │ └── ListSpaceItemDecoration.kt │ │ │ └── resource │ │ │ ├── AnimInfo.kt │ │ │ ├── UISpan.kt │ │ │ └── UIText.kt │ └── res │ │ ├── anim │ │ ├── anim_bounce.xml │ │ ├── anim_fade_in.xml │ │ ├── anim_fade_out.xml │ │ ├── anim_fadein_up.xml │ │ ├── anim_jump.xml │ │ ├── anim_shake.xml │ │ ├── anim_slide_in_bottom.xml │ │ ├── anim_slide_in_left.xml │ │ ├── anim_slide_in_right.xml │ │ ├── anim_slide_out_left.xml │ │ ├── anim_slide_out_right.xml │ │ ├── anim_slide_out_top.xml │ │ └── anim_stamp.xml │ │ ├── color │ │ ├── black_12.xml │ │ ├── black_36.xml │ │ ├── black_50.xml │ │ ├── black_60.xml │ │ ├── on_primary_12.xml │ │ ├── on_surface_12.xml │ │ ├── on_surface_50.xml │ │ ├── on_surface_60.xml │ │ ├── on_surface_87.xml │ │ ├── on_surface_9.xml │ │ └── primary.xml │ │ ├── drawable-night │ │ ├── ic_widget_accommodation.xml │ │ ├── ic_widget_cafe.xml │ │ ├── ic_widget_convenience.xml │ │ ├── ic_widget_culture.xml │ │ ├── ic_widget_market.xml │ │ └── ic_widget_restaurant.xml │ │ ├── drawable-nodpi │ │ └── widget_gifticon_preview.jpg │ │ ├── drawable │ │ ├── anim_logo.xml │ │ ├── bg_black_50.xml │ │ ├── bg_bottom_sheet_handle.xml │ │ ├── bg_circle_black_50.xml │ │ ├── bg_corner_top_20.xml │ │ ├── bg_gallery.xml │ │ ├── bg_gallery_selected.xml │ │ ├── bg_gifticon_memo.xml │ │ ├── bg_history_cancel.xml │ │ ├── bg_history_init.xml │ │ ├── bg_history_modify.xml │ │ ├── bg_history_use.xml │ │ ├── bg_map_bottom_sheet_24.xml │ │ ├── bg_on_surface_12.xml │ │ ├── bg_on_surface_50.xml │ │ ├── bg_origin_gifticon.xml │ │ ├── bg_primary_corner_4.xml │ │ ├── bg_splash.xml │ │ ├── bg_stroke_bottom.xml │ │ ├── bg_widget_small_6.xml │ │ ├── bottom_sheet_background.xml │ │ ├── btn_main_floating_add.xml │ │ ├── ic_add_goto_gallery.xml │ │ ├── ic_add_warning_badge.xml │ │ ├── ic_arrow_forward.xml │ │ ├── ic_back.xml │ │ ├── ic_check.xml │ │ ├── ic_confirm.xml │ │ ├── ic_crop.xml │ │ ├── ic_double_arrow_down.xml │ │ ├── ic_edit_gifticon_calendar.xml │ │ ├── ic_fingerprint.xml │ │ ├── ic_history.xml │ │ ├── ic_item_invalid.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ic_location.xml │ │ ├── ic_main_menu_home.xml │ │ ├── ic_main_menu_list.xml │ │ ├── ic_main_menu_setting.xml │ │ ├── ic_marker_accommodation.xml │ │ ├── ic_marker_base.xml │ │ ├── ic_marker_cafe.xml │ │ ├── ic_marker_convenience.xml │ │ ├── ic_marker_culture.xml │ │ ├── ic_marker_market.xml │ │ ├── ic_marker_restaurant.xml │ │ ├── ic_mode_edit.xml │ │ ├── ic_origin_gifticon.xml │ │ ├── ic_outline_info.xml │ │ ├── ic_pin_backspace.xml │ │ ├── ic_pin_border.xml │ │ ├── ic_pin_filled.xml │ │ ├── ic_question.xml │ │ ├── ic_remove.xml │ │ ├── ic_share.xml │ │ ├── ic_splash_beep.xml │ │ ├── ic_warning.xml │ │ ├── ic_widget_accommodation.xml │ │ ├── ic_widget_cafe.xml │ │ ├── ic_widget_convenience.xml │ │ ├── ic_widget_culture.xml │ │ ├── ic_widget_market.xml │ │ ├── ic_widget_refresh_24.xml │ │ ├── ic_widget_restaurant.xml │ │ ├── img_item_delete.xml │ │ ├── img_item_invalid.xml │ │ ├── img_stamp.xml │ │ ├── ripple_add_gifticon_candidate.xml │ │ ├── ripple_circle_on_primary_12.xml │ │ ├── ripple_circle_on_surface_12.xml │ │ ├── ripple_primary_corner_4.xml │ │ ├── ripple_rect_corner_8_on_primary_12.xml │ │ ├── ripple_rect_corner_8_on_surface_12.xml │ │ ├── tc_on_primary_disabled.xml │ │ └── tc_on_primary_disabled_night.xml │ │ ├── layout │ │ ├── activity_add_gifticon.xml │ │ ├── activity_crop_gifticon.xml │ │ ├── activity_gallery.xml │ │ ├── activity_gifticon_detail.xml │ │ ├── activity_main.xml │ │ ├── activity_map.xml │ │ ├── activity_modify_gifticon.xml │ │ ├── activity_security.xml │ │ ├── activity_sign_in.xml │ │ ├── dialog_confirmation.xml │ │ ├── dialog_fingerprint_legacy.xml │ │ ├── dialog_history.xml │ │ ├── dialog_large_barcode.xml │ │ ├── dialog_map_gifticons.xml │ │ ├── dialog_origin_image.xml │ │ ├── dialog_progress.xml │ │ ├── dialog_spinner_date_picker.xml │ │ ├── dialog_use_gifticon.xml │ │ ├── fragment_cash_card_gifticon_info.xml │ │ ├── fragment_check_location.xml │ │ ├── fragment_fingerprint.xml │ │ ├── fragment_gifticon_list.xml │ │ ├── fragment_home.xml │ │ ├── fragment_home_container.xml │ │ ├── fragment_home_empty.xml │ │ ├── fragment_pin.xml │ │ ├── fragment_security_setting.xml │ │ ├── fragment_setting.xml │ │ ├── fragment_setting_main.xml │ │ ├── fragment_sign_in.xml │ │ ├── fragment_standard_gifticon_info.xml │ │ ├── fragment_used_gifticon.xml │ │ ├── item_add_candidate_gifticon.xml │ │ ├── item_add_goto_gallery.xml │ │ ├── item_gallery.xml │ │ ├── item_gallery_header.xml │ │ ├── item_gifticon_horizontal.xml │ │ ├── item_gifticon_vertical.xml │ │ ├── item_gifticon_vertical_loading.xml │ │ ├── item_history.xml │ │ ├── item_history_header.xml │ │ ├── item_near_gifticon_vertical.xml │ │ ├── item_selected_gallery.xml │ │ └── widget_loading_layout.xml │ │ ├── menu │ │ ├── menu_gifticon_detail.xml │ │ └── menu_main_navigation.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── navigation │ │ └── nav_graph.xml │ │ ├── raw │ │ └── lottie_not_found.json │ │ ├── values-night │ │ ├── colors.xml │ │ └── themes.xml │ │ ├── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ ├── data_extraction_rules.xml │ │ └── gifticon_widget_provider.xml │ └── test │ └── kotlin │ └── com │ └── lighthouse │ └── data │ └── TextParseTest.kt └── settings.gradle.kts /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @boostcampwm-2022/beep -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | resolved: #number 2 | 3 | ## 작업 내용 4 | 5 | > 어떤 작업을 했는지 적어주세요! 6 | 7 | ## 체크리스트 8 | - [ ] Assignees 설정 9 | - [ ] Labels 설정 10 | - [ ] Projects 설정 11 | - [ ] Milestone 설정 12 | 13 | ## 동작 화면 14 | 15 | > 존재하지 않는다면 패스해주세요! 16 | 17 | ## 버그 18 | 19 | > 존재하지 않는다면 패스해주세요! -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | test: 2 | - domain/src/test/**/* 3 | - presentation/src/test/**/* 4 | - presentation/src/androidTest/**/* 5 | - data/src/test/**/* 6 | 7 | chore: 8 | - app/*.gradle 9 | - build.gradle 10 | - buildSrc/**/* 11 | 12 | style: 13 | - presentation/src/main/res/**/* 14 | 15 | feat: 16 | - app/**/* 17 | - data/src/**/* 18 | - domain/src/**/* 19 | - presentation/src/main/java/**/* 20 | 21 | docs: 22 | - README.md 23 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Labeler" 2 | on: 3 | pull_request_target: 4 | branches: 5 | - develop 6 | 7 | jobs: 8 | label: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/labeler@v2 13 | with: 14 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 15 | -------------------------------------------------------------------------------- /.github/workflows/reviewKtlint.yml: -------------------------------------------------------------------------------- 1 | name: ktlint 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - develop 8 | jobs: 9 | ktlint: 10 | name: Check Code Quality 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Clone repo 15 | uses: actions/checkout@master 16 | with: 17 | fetch-depth: 1 18 | - name: ktlint 19 | uses: ScaCap/action-ktlint@master 20 | with: 21 | github_token: ${{ secrets.github_token }} 22 | reporter: github-pr-review 23 | android: true 24 | fail_on_error: true 25 | level: warning 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .DS_Store 5 | /build 6 | /captures 7 | .externalNativeBuild 8 | .cxx 9 | local.properties 10 | /.idea/ 11 | /buildSrc/build/ 12 | build-logic/convention/build 13 | build-logic/build -------------------------------------------------------------------------------- /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.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/java/com/lighthouse/di/HTTPRequestInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.di 2 | 3 | import com.lighthouse.beep.BuildConfig 4 | import okhttp3.Interceptor 5 | import okhttp3.Response 6 | 7 | class HTTPRequestInterceptor : Interceptor { 8 | 9 | override fun intercept(chain: Interceptor.Chain): Response { 10 | val origin = chain.request() 11 | val request = origin.newBuilder() 12 | .addHeader("Content-Type", "application/json") 13 | .addHeader("Authorization", "KakaoAK ${BuildConfig.kakaoSearchId}") 14 | .build() 15 | return chain.proceed(request) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/lighthouse/di/WorkManagerInitializer.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.di 2 | 3 | import android.content.Context 4 | import androidx.startup.Initializer 5 | import androidx.work.Configuration 6 | import androidx.work.WorkManager 7 | import dagger.Module 8 | import dagger.Provides 9 | import dagger.hilt.InstallIn 10 | import dagger.hilt.android.qualifiers.ApplicationContext 11 | import dagger.hilt.components.SingletonComponent 12 | import javax.inject.Singleton 13 | 14 | @Module 15 | @InstallIn(SingletonComponent::class) 16 | object WorkManagerInitializer : Initializer { 17 | 18 | @Provides 19 | @Singleton 20 | override fun create(@ApplicationContext context: Context): WorkManager { 21 | val configuration = Configuration.Builder().build() 22 | WorkManager.initialize(context, configuration) 23 | return WorkManager.getInstance(context) 24 | } 25 | 26 | override fun dependencies(): List>> { 27 | return emptyList() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/lighthouse/utils/log/CustomTimberTree.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.utils.log 2 | 3 | import timber.log.Timber 4 | import javax.inject.Inject 5 | 6 | class CustomTimberTree @Inject constructor() : Timber.DebugTree() { 7 | override fun createStackElementTag(element: StackTraceElement): String { 8 | return "${element.className}:${element.lineNumber}#${element.methodName}" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /build-logic/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /build-logic/convention/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /build-logic/convention/src/main/java/AndroidApplicationComposeConventionPlugin.kt: -------------------------------------------------------------------------------- 1 | import com.android.build.gradle.internal.dsl.BaseAppModuleExtension 2 | import com.lighthouse.convention.configureAndroidCompose 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.Project 5 | import org.gradle.kotlin.dsl.getByType 6 | 7 | class AndroidApplicationComposeConventionPlugin : Plugin { 8 | override fun apply(target: Project) { 9 | with(target) { 10 | pluginManager.apply("com.android.application") 11 | val extension = extensions.getByType() 12 | configureAndroidCompose(extension) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /build-logic/convention/src/main/java/AndroidHiltConventionPlugin.kt: -------------------------------------------------------------------------------- 1 | import com.lighthouse.convention.findVersionCatalog 2 | import com.lighthouse.convention.implementation 3 | import com.lighthouse.convention.kapt 4 | import org.gradle.api.Plugin 5 | import org.gradle.api.Project 6 | import org.gradle.kotlin.dsl.dependencies 7 | 8 | class AndroidHiltConventionPlugin : Plugin { 9 | override fun apply(target: Project) { 10 | with(target) { 11 | with(pluginManager) { 12 | apply("kotlin-kapt") 13 | apply("dagger.hilt.android.plugin") 14 | } 15 | 16 | val libs = findVersionCatalog() 17 | 18 | dependencies { 19 | implementation(libs.findLibrary("dagger-hilt-android")) 20 | kapt(libs.findLibrary("dagger-hilt-android-compiler")) 21 | } 22 | 23 | kapt { 24 | correctErrorTypes = true 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /build-logic/convention/src/main/java/AndroidLibraryComposeConventionPlugin.kt: -------------------------------------------------------------------------------- 1 | import com.android.build.gradle.LibraryExtension 2 | import com.lighthouse.convention.configureAndroidCompose 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.Project 5 | import org.gradle.kotlin.dsl.getByType 6 | 7 | class AndroidLibraryComposeConventionPlugin : Plugin { 8 | override fun apply(target: Project) { 9 | with(target) { 10 | pluginManager.apply("com.android.library") 11 | val extension = extensions.getByType() 12 | configureAndroidCompose(extension) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /build-logic/convention/src/main/java/AndroidLibraryConventionPlugin.kt: -------------------------------------------------------------------------------- 1 | import com.android.build.gradle.LibraryExtension 2 | import com.lighthouse.convention.configureAndroid 3 | import com.lighthouse.convention.configureKotlin 4 | import org.gradle.api.Plugin 5 | import org.gradle.api.Project 6 | import org.gradle.kotlin.dsl.configure 7 | 8 | class AndroidLibraryConventionPlugin : Plugin { 9 | override fun apply(target: Project) { 10 | with(target) { 11 | with(pluginManager) { 12 | apply("com.android.library") 13 | apply("org.jetbrains.kotlin.android") 14 | } 15 | 16 | configureAndroid() 17 | 18 | extensions.configure { 19 | configureKotlin(this) 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /build-logic/convention/src/main/java/JavaLibraryConventionPlugin.kt: -------------------------------------------------------------------------------- 1 | import com.lighthouse.convention.ProjectConfigurations 2 | import com.lighthouse.convention.java 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.Project 5 | 6 | class JavaLibraryConventionPlugin : Plugin { 7 | override fun apply(target: Project) { 8 | with(target) { 9 | with(pluginManager) { 10 | apply("java-library") 11 | apply("org.jetbrains.kotlin.jvm") 12 | } 13 | 14 | java { 15 | sourceCompatibility = ProjectConfigurations.javaVer 16 | targetCompatibility = ProjectConfigurations.javaVer 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /build-logic/convention/src/main/java/com/lighthouse/convention/AndroidCompose.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("UnstableApiUsage") // ktlint-disable filename 2 | 3 | package com.lighthouse.convention 4 | 5 | import com.android.build.api.dsl.CommonExtension 6 | import org.gradle.api.Project 7 | import org.gradle.kotlin.dsl.dependencies 8 | 9 | internal fun Project.configureAndroidCompose( 10 | commonExtension: CommonExtension<*, *, *, *> 11 | ) { 12 | val libs = findVersionCatalog() 13 | 14 | commonExtension.apply { 15 | buildFeatures.compose = true 16 | 17 | composeOptions { 18 | kotlinCompilerExtensionVersion = libs.findVersion("compose-compiler").get().toString() 19 | } 20 | } 21 | 22 | dependencies { 23 | api(platform(libs.findLibrary("androidX-compose-bom").get())) 24 | implementation(libs.findBundle("androidX-compose")) 25 | implementation(libs.findBundle("androidX-compose-lifecycle")) 26 | debugImplementation(libs.findBundle("androidX-compose-debug")) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /build-logic/convention/src/main/java/com/lighthouse/convention/DependencyHandlerExt.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.convention 2 | 3 | import org.gradle.api.artifacts.Dependency 4 | import org.gradle.api.artifacts.dsl.DependencyHandler 5 | import org.gradle.api.provider.Provider 6 | import java.util.Optional 7 | 8 | internal fun DependencyHandler.implementation( 9 | dependencyNotation: Optional> 10 | ): Dependency? = add("implementation", dependencyNotation.get()) 11 | 12 | internal fun DependencyHandler.debugImplementation( 13 | dependencyNotation: Optional> 14 | ): Dependency? = add("debugImplementation", dependencyNotation.get()) 15 | 16 | internal fun DependencyHandler.kapt( 17 | dependencyNotation: Optional> 18 | ): Dependency? = add("kapt", dependencyNotation.get()) 19 | 20 | internal fun DependencyHandler.api( 21 | dependencyNotation: Provider 22 | ): Dependency? = add("api", dependencyNotation) 23 | -------------------------------------------------------------------------------- /build-logic/convention/src/main/java/com/lighthouse/convention/ProjectConfigurations.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.convention 2 | 3 | import org.gradle.api.JavaVersion 4 | 5 | object ProjectConfigurations { 6 | const val compileSdk = 33 7 | const val minSdk = 23 8 | const val targetSdk = 33 9 | val javaVer = JavaVersion.VERSION_11 10 | } 11 | -------------------------------------------------------------------------------- /build-logic/convention/src/main/java/com/lighthouse/convention/ProjectExt.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.convention 2 | 3 | import org.gradle.api.Project 4 | import org.gradle.api.artifacts.VersionCatalog 5 | import org.gradle.api.artifacts.VersionCatalogsExtension 6 | import org.gradle.kotlin.dsl.getByType 7 | 8 | fun Project.findVersionCatalog(): VersionCatalog = 9 | extensions.getByType().named("libs") 10 | -------------------------------------------------------------------------------- /build-logic/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | @file:Suppress("UnstableApiUsage") 2 | 3 | enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 4 | 5 | dependencyResolutionManagement { 6 | repositories { 7 | google() 8 | mavenCentral() 9 | } 10 | 11 | versionCatalogs { 12 | create("libs") { 13 | from(files("../gradle/libs.versions.toml")) 14 | } 15 | } 16 | } 17 | 18 | rootProject.name = "build-logic" 19 | include(":convention") 20 | -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /data/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/data/consumer-rules.pro -------------------------------------------------------------------------------- /data/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.kts. 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 -------------------------------------------------------------------------------- /data/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/database/converter/DateConverter.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.database.converter 2 | 3 | import androidx.room.TypeConverter 4 | import java.util.Date 5 | 6 | class DateConverter { 7 | @TypeConverter 8 | fun fromTimestamp(value: Long?): Date? { 9 | return value?.let { Date(it) } 10 | } 11 | 12 | @TypeConverter 13 | fun dateToTimestamp(date: Date?): Long? { 14 | return date?.time 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/database/converter/DmsConverter.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.database.converter 2 | 3 | import androidx.room.TypeConverter 4 | import com.lighthouse.domain.Dms 5 | import com.lighthouse.domain.LocationConverter 6 | 7 | class DmsConverter { 8 | 9 | @TypeConverter 10 | fun decimalToDms(value: Double?): Dms? { 11 | return value?.let { LocationConverter.toMinDms(it) } 12 | } 13 | 14 | @TypeConverter 15 | fun dmsToDecimal(dms: Dms?): Double? { 16 | return dms?.let { LocationConverter.convertToDD(it) } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/database/converter/RectConverter.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.database.converter 2 | 3 | import android.graphics.Rect 4 | import androidx.core.text.isDigitsOnly 5 | import androidx.room.TypeConverter 6 | 7 | class RectConverter { 8 | 9 | @TypeConverter 10 | fun rectToString(rect: Rect?): String? { 11 | return rect?.let { 12 | "${it.left},${it.top},${it.right},${it.bottom}" 13 | } 14 | } 15 | 16 | @TypeConverter 17 | fun stringToRect(string: String?): Rect? { 18 | val data = string?.split(",") ?: return null 19 | if (data.size == 4 && data.all { it.isDigitsOnly() }) { 20 | return Rect(data[0].toInt(), data[1].toInt(), data[2].toInt(), data[3].toInt()) 21 | } 22 | return null 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/database/converter/UriConverter.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.database.converter 2 | 3 | import android.net.Uri 4 | import androidx.room.TypeConverter 5 | 6 | class UriConverter { 7 | @TypeConverter 8 | fun fromUri(uri: Uri?): String { 9 | return uri?.toString() ?: "" 10 | } 11 | 12 | @TypeConverter 13 | fun stringToUri(string: String?): Uri? { 14 | string ?: return null 15 | if (string == "") { 16 | return null 17 | } 18 | return Uri.parse(string) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/database/entity/BrandWithSections.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.database.entity 2 | 3 | import androidx.room.Embedded 4 | import androidx.room.Relation 5 | 6 | data class BrandWithSections( 7 | @Embedded val sectionEntity: SectionEntity, 8 | @Relation( 9 | parentColumn = PARENT_COLUMN_ID, 10 | entityColumn = ENTITY_COLUMN_ID 11 | ) 12 | val brands: List 13 | ) { 14 | 15 | companion object { 16 | private const val PARENT_COLUMN_ID = "section_id" 17 | private const val ENTITY_COLUMN_ID = "parent_section_id" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/database/entity/GifticonCropEntity.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.database.entity 2 | 3 | import android.graphics.Rect 4 | import androidx.room.ColumnInfo 5 | import androidx.room.Entity 6 | import androidx.room.ForeignKey 7 | import androidx.room.PrimaryKey 8 | import com.lighthouse.database.entity.GifticonCropEntity.Companion.GIFTICON_CROP_TABLE 9 | 10 | @Entity( 11 | tableName = GIFTICON_CROP_TABLE, 12 | foreignKeys = [ 13 | ForeignKey( 14 | entity = GifticonEntity::class, 15 | parentColumns = arrayOf("id"), 16 | childColumns = arrayOf("gifticon_id"), 17 | onDelete = ForeignKey.CASCADE 18 | ) 19 | ] 20 | ) 21 | data class GifticonCropEntity( 22 | @PrimaryKey 23 | @ColumnInfo(name = "gifticon_id") 24 | val gifticonId: String, 25 | @ColumnInfo(name = "cropped_rect") 26 | val croppedRect: Rect 27 | ) { 28 | companion object { 29 | const val GIFTICON_CROP_TABLE = "gifticon_crop_table" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/database/entity/SectionEntity.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.database.entity 2 | 3 | import androidx.room.ColumnInfo 4 | import androidx.room.Entity 5 | import androidx.room.PrimaryKey 6 | import com.lighthouse.database.entity.SectionEntity.Companion.SECTION_TABLE 7 | import com.lighthouse.domain.Dms 8 | import java.util.Date 9 | 10 | @Entity(tableName = SECTION_TABLE) 11 | data class SectionEntity( 12 | @PrimaryKey 13 | @ColumnInfo(name = "section_id") 14 | val id: String, 15 | @ColumnInfo(name = "search_date") val searchDate: Date, 16 | @ColumnInfo(name = "x") val x: Dms, 17 | @ColumnInfo(name = "y") val y: Dms 18 | ) { 19 | 20 | companion object { 21 | const val SECTION_TABLE = "section_table" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/database/mapper/GifticonCropEntityMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.database.mapper 2 | 3 | import com.lighthouse.database.entity.GifticonCropEntity 4 | import com.lighthouse.domain.model.GifticonCrop 5 | import com.lighthouse.mapper.toDomain 6 | 7 | fun GifticonCropEntity.toDomain(): GifticonCrop { 8 | return GifticonCrop( 9 | gifticonId = gifticonId, 10 | rect = croppedRect.toDomain() 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/database/mapper/GifticonForUpdateMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.database.mapper 2 | 3 | import android.net.Uri 4 | import com.lighthouse.database.entity.GifticonWithCrop 5 | import com.lighthouse.domain.model.GifticonForUpdate 6 | import com.lighthouse.mapper.toEntity 7 | 8 | fun GifticonForUpdate.toEntity(newCroppedUri: Uri?): GifticonWithCrop { 9 | return GifticonWithCrop( 10 | id = id, 11 | userId = userId, 12 | hasImage = hasImage, 13 | croppedUri = newCroppedUri ?: if (croppedUri.isNotEmpty()) Uri.parse(croppedUri) else null, 14 | name = name, 15 | brand = brandName, 16 | expireAt = expiredAt, 17 | barcode = barcode, 18 | isCashCard = isCashCard, 19 | balance = balance, 20 | memo = memo, 21 | croppedRect = croppedRect.toEntity(), 22 | isUsed = isUsed, 23 | createdAt = createdAt 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/datasource/auth/AuthDataSource.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.datasource.auth 2 | 3 | interface AuthDataSource { 4 | 5 | fun getCurrentUserId(): String 6 | } 7 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/datasource/auth/AuthDataSourceImpl.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.datasource.auth 2 | 3 | import com.google.firebase.auth.FirebaseAuth 4 | import javax.inject.Inject 5 | 6 | class AuthDataSourceImpl @Inject constructor( 7 | private val firebaseAuth: FirebaseAuth 8 | ) : AuthDataSource { 9 | 10 | override fun getCurrentUserId(): String { 11 | return firebaseAuth.currentUser?.uid ?: GUEST_ID 12 | } 13 | 14 | companion object { 15 | private const val GUEST_ID = "Guest" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/datasource/brand/BrandLocalDataSource.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.datasource.brand 2 | 3 | import com.lighthouse.database.entity.BrandLocationEntity 4 | import com.lighthouse.domain.Dms 5 | import com.lighthouse.domain.model.BrandPlaceInfo 6 | 7 | interface BrandLocalDataSource { 8 | 9 | suspend fun getBrands(x: Dms, y: Dms, brandName: String): Result> 10 | 11 | suspend fun insertBrands( 12 | brandPlaceInfos: List, 13 | x: Dms, 14 | y: Dms, 15 | brandName: String 16 | ) 17 | 18 | suspend fun isNearBrand(x: Dms, y: Dms, brandName: String): List? 19 | 20 | suspend fun removeExpirationBrands() 21 | } 22 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/datasource/brand/BrandRemoteDataSource.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.datasource.brand 2 | 3 | import com.lighthouse.domain.Dms 4 | import com.lighthouse.model.BrandPlaceInfoDataContainer 5 | 6 | interface BrandRemoteDataSource { 7 | 8 | suspend fun getBrandPlaceInfo( 9 | brandName: String, 10 | x: Dms, 11 | y: Dms, 12 | size: Int 13 | ): Result> 14 | } 15 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/datasource/gallery/GalleryImageLocalSource.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.datasource.gallery 2 | 3 | import com.lighthouse.domain.model.GalleryImage 4 | 5 | interface GalleryImageLocalSource { 6 | suspend fun getImages(page: Int, limit: Int): List 7 | } 8 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/mapper/BrandPlaceInfoDataContainerMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.mapper 2 | 3 | import com.lighthouse.domain.model.BrandPlaceInfo 4 | import com.lighthouse.model.BrandPlaceInfoDataContainer 5 | 6 | internal fun List.toDomain(brandName: String): List { 7 | return this.map { 8 | BrandPlaceInfo( 9 | addressName = it.addressName, 10 | placeName = it.placeName, 11 | categoryName = it.categoryGroupName, 12 | placeUrl = it.placeUrl, 13 | brand = brandName, 14 | x = it.x, 15 | y = it.y 16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/mapper/ErrorMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.mapper 2 | 3 | import com.lighthouse.domain.model.BeepError 4 | import com.lighthouse.model.BeepErrorData 5 | 6 | internal fun BeepErrorData.toDomain(): BeepError = when (this) { 7 | is BeepErrorData.NetworkFailure -> BeepError.NetworkFailure 8 | } 9 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/mapper/GifticonCropMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.mapper 2 | 3 | import com.lighthouse.database.entity.GifticonCropEntity 4 | import com.lighthouse.domain.model.GifticonCrop 5 | 6 | fun GifticonCrop.toEntity(): GifticonCropEntity { 7 | return GifticonCropEntity( 8 | gifticonId = gifticonId, 9 | croppedRect = rect.toEntity() 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/mapper/GifticonEntityMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.mapper 2 | 3 | import com.lighthouse.database.entity.GifticonEntity 4 | import com.lighthouse.domain.model.Gifticon 5 | 6 | fun GifticonEntity.toDomain(): Gifticon { 7 | return Gifticon( 8 | id = id, 9 | createdAt = createdAt, 10 | userId = userId, 11 | hasImage = hasImage, 12 | croppedUri = croppedUri.toString(), 13 | name = name, 14 | brand = brand, 15 | expireAt = expireAt, 16 | barcode = barcode, 17 | isCashCard = isCashCard, 18 | balance = balance, 19 | memo = memo, 20 | isUsed = isUsed 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/mapper/GifticonRecognizeInfoMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.mapper 2 | 3 | import android.net.Uri 4 | import com.lighthouse.domain.model.GifticonForAddition 5 | import com.lighthouse.util.recognizer.GifticonRecognizeInfo 6 | 7 | fun GifticonRecognizeInfo.toDomain(originUri: Uri, croppedUri: Uri?): GifticonForAddition { 8 | return GifticonForAddition( 9 | true, 10 | name, 11 | brand, 12 | barcode, 13 | expiredAt, 14 | isCashCard, 15 | balance, 16 | originUri.toString(), 17 | croppedUri?.toString() ?: "", 18 | croppedRect.toDomain(), 19 | "" 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/mapper/RectMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.mapper 2 | 3 | import android.graphics.Rect 4 | import com.lighthouse.domain.model.Rectangle 5 | 6 | fun Rect.toDomain(): Rectangle { 7 | return Rectangle(left, top, right, bottom) 8 | } 9 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/mapper/RectangleMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.mapper 2 | 3 | import android.graphics.Rect 4 | import com.lighthouse.domain.model.Rectangle 5 | 6 | fun Rectangle.toEntity(): Rect { 7 | return Rect(left, top, right, bottom) 8 | } 9 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/model/BeepErrorData.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.model 2 | 3 | sealed class BeepErrorData( 4 | override val message: String? = null, 5 | override val cause: Throwable? = null 6 | ) : Exception(message, cause) { 7 | 8 | object NetworkFailure : BeepErrorData() 9 | } 10 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/model/GifticonImageResult.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.model 2 | 3 | import android.net.Uri 4 | 5 | data class GifticonImageResult( 6 | val sampleSize: Int, 7 | val outputCroppedUri: Uri 8 | ) 9 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/network/NetworkApiService.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.network 2 | 3 | import com.lighthouse.model.BrandPlaceInfoDataContainer 4 | import retrofit2.http.GET 5 | import retrofit2.http.Query 6 | 7 | interface NetworkApiService { 8 | 9 | @GET("v2/local/search/keyword.json") 10 | suspend fun getAllBrandPlaceInfo( 11 | @Query("query") query: String, 12 | @Query("rect") rect: String, 13 | @Query("size") size: Int, 14 | @Query("category_group_code") groupCode: String = CATEGORY_GROUP_CODE 15 | ): BrandPlaceInfoDataContainer 16 | 17 | companion object { 18 | private const val CATEGORY_GROUP_CODE = "MT1,CS2,CT1,AD5,FD6,CE7" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/repository/AuthRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.repository 2 | 3 | import com.lighthouse.datasource.auth.AuthDataSource 4 | import com.lighthouse.domain.repository.AuthRepository 5 | import javax.inject.Inject 6 | 7 | class AuthRepositoryImpl @Inject constructor( 8 | private val authDataSource: AuthDataSource 9 | ) : AuthRepository { 10 | 11 | override fun getCurrentUserId(): String { 12 | return authDataSource.getCurrentUserId() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/repository/GalleryImageRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.repository 2 | 3 | import androidx.paging.Pager 4 | import androidx.paging.PagingConfig 5 | import androidx.paging.PagingData 6 | import com.lighthouse.datasource.gallery.GalleryImageLocalSource 7 | import com.lighthouse.datasource.gallery.GalleryImagePagingSource 8 | import com.lighthouse.domain.model.GalleryImage 9 | import com.lighthouse.domain.repository.GalleryImageRepository 10 | import kotlinx.coroutines.flow.Flow 11 | import javax.inject.Inject 12 | 13 | class GalleryImageRepositoryImpl @Inject constructor( 14 | private val localSource: GalleryImageLocalSource 15 | ) : GalleryImageRepository { 16 | 17 | override fun getImages(pageSize: Int): Flow> { 18 | return Pager( 19 | config = PagingConfig(pageSize = pageSize, enablePlaceholders = false), 20 | pagingSourceFactory = { 21 | GalleryImagePagingSource(localSource, 0, pageSize) 22 | } 23 | ).flow 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/repository/LocationRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.repository 2 | 3 | import com.lighthouse.datasource.location.SharedLocationManager 4 | import com.lighthouse.domain.repository.LocationRepository 5 | import javax.inject.Inject 6 | 7 | class LocationRepositoryImpl @Inject constructor( 8 | private val sharedLocationManager: SharedLocationManager 9 | ) : LocationRepository { 10 | 11 | override fun getLocations() = sharedLocationManager.locationFlow() 12 | } 13 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/repository/SecurityRepositoryImpl.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.repository 2 | 3 | import com.lighthouse.domain.repository.SecurityRepository 4 | import com.lighthouse.util.CryptoObjectHelper 5 | import javax.crypto.Cipher 6 | 7 | class SecurityRepositoryImpl : SecurityRepository { 8 | override fun getFingerprintCipher(): Cipher { 9 | return CryptoObjectHelper.getFingerprintCipher() 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/UUID.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util 2 | 3 | import java.util.UUID 4 | 5 | object UUID { 6 | fun generate() = UUID.randomUUID().toString() 7 | } 8 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/BalanceRecognizer.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer 2 | 3 | import android.graphics.Bitmap 4 | import com.lighthouse.util.recognizer.parser.BalanceParser 5 | import kotlinx.coroutines.Dispatchers 6 | import kotlinx.coroutines.withContext 7 | 8 | class BalanceRecognizer { 9 | 10 | private val balanceParser = BalanceParser() 11 | 12 | private val textRecognizer = TextRecognizer() 13 | 14 | suspend fun recognize(bitmap: Bitmap) = withContext(Dispatchers.IO) { 15 | val inputs = textRecognizer.recognize(bitmap) 16 | balanceParser.parseCashCard(inputs) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/BarcodeRecognizer.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer 2 | 3 | import android.graphics.Bitmap 4 | import com.lighthouse.util.recognizer.parser.BarcodeParser 5 | import kotlinx.coroutines.Dispatchers 6 | import kotlinx.coroutines.withContext 7 | 8 | class BarcodeRecognizer { 9 | 10 | private val barcodeParser = BarcodeParser() 11 | 12 | private val textRecognizer = TextRecognizer() 13 | 14 | suspend fun recognize(bitmap: Bitmap) = withContext(Dispatchers.IO) { 15 | val inputs = textRecognizer.recognize(bitmap) 16 | barcodeParser.parseBarcode(inputs) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/ExpiredRecognizer.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer 2 | 3 | import android.graphics.Bitmap 4 | import com.lighthouse.util.recognizer.parser.ExpiredParser 5 | import kotlinx.coroutines.Dispatchers 6 | import kotlinx.coroutines.withContext 7 | 8 | class ExpiredRecognizer { 9 | 10 | private val expiredParser = ExpiredParser() 11 | 12 | private val textRecognizer = TextRecognizer() 13 | 14 | suspend fun recognize(bitmap: Bitmap) = withContext(Dispatchers.IO) { 15 | val inputs = textRecognizer.recognize(bitmap) 16 | expiredParser.parseExpiredDate(inputs) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/GifticonRecognizeInfo.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.Rect 5 | import java.util.Date 6 | 7 | data class GifticonRecognizeInfo( 8 | val name: String = "", 9 | val brand: String = "", 10 | val expiredAt: Date = Date(0), 11 | val barcode: String = "", 12 | val isCashCard: Boolean = false, 13 | val balance: Int = 0, 14 | val candidate: List = listOf(), 15 | val croppedImage: Bitmap? = null, 16 | val croppedRect: Rect = Rect() 17 | ) 18 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/parser/BalanceParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.parser 2 | 3 | class BalanceParser { 4 | private val cashCardFilterRegex = listOf( 5 | CashCardRegex("\\b(\\d{0,3}[,]?\\d{0,3}[,]\\d{1,3})".toRegex(), 1), 6 | CashCardRegex("(\\d+)천원".toRegex(), 1000), 7 | CashCardRegex("(\\d+)만원".toRegex(), 10000), 8 | CashCardRegex("(\\d+)십만원".toRegex(), 100000) 9 | ) 10 | 11 | fun parseCashCard(inputs: List): BalanceParserResult { 12 | val balance = inputs.firstNotNullOfOrNull { text -> 13 | cashCardFilterRegex.firstNotNullOfOrNull { cashCard -> 14 | val value = cashCard.regex.find(text)?.groupValues?.getOrNull(1) 15 | value?.filter { it.isDigit() }?.toInt()?.times(cashCard.unit) 16 | } 17 | } ?: 0 18 | 19 | return BalanceParserResult(balance = if (balance >= 100) balance else 0) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/parser/BalanceParserResult.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.parser 2 | 3 | data class BalanceParserResult( 4 | val balance: Int 5 | ) 6 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/parser/BarcodeParserResult.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.parser 2 | 3 | data class BarcodeParserResult( 4 | val barcode: String, 5 | val filtered: List 6 | ) 7 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/parser/CashCardRegex.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.parser 2 | 3 | data class CashCardRegex( 4 | val regex: Regex, 5 | val unit: Int 6 | ) 7 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/parser/ExpiredParserResult.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.parser 2 | 3 | import java.util.Date 4 | 5 | data class ExpiredParserResult( 6 | val expired: Date, 7 | val filtered: List 8 | ) 9 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/processor/GifticonProcessImage.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.processor 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.Rect 5 | 6 | data class GifticonProcessImage( 7 | val bitmap: Bitmap, 8 | val rect: Rect 9 | ) 10 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/processor/GifticonProcessResult.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.processor 2 | 3 | class GifticonProcessResult( 4 | val image: GifticonProcessImage, 5 | val textList: List 6 | ) 7 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/processor/GifticonProcessText.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.processor 2 | 3 | import android.graphics.Bitmap 4 | 5 | data class GifticonProcessText( 6 | val tag: GifticonProcessTextTag, 7 | val bitmap: Bitmap 8 | ) 9 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/processor/GifticonProcessTextTag.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.processor 2 | 3 | enum class GifticonProcessTextTag { 4 | GIFTICON_NAME, 5 | BRAND_NAME, 6 | GIFTICON_BRAND_NAME, 7 | BRAND_GIFTICON_NAME 8 | } 9 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/giftishow/GiftishowParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.giftishow 2 | 3 | import com.lighthouse.util.recognizer.parser.BaseParser 4 | 5 | class GiftishowParser : BaseParser() { 6 | 7 | override val keywordText = listOf( 8 | "기프티쇼", 9 | "giftishow" 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/giftishow/GiftishowProcessor.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.giftishow 2 | 3 | import android.graphics.Bitmap 4 | import com.lighthouse.util.recognizer.processor.BaseProcessor 5 | import com.lighthouse.util.recognizer.processor.GifticonProcessImage 6 | import com.lighthouse.util.recognizer.processor.GifticonProcessText 7 | import com.lighthouse.util.recognizer.processor.GifticonProcessTextTag 8 | 9 | class GiftishowProcessor : BaseProcessor() { 10 | 11 | override fun processTextImage(bitmap: Bitmap): List { 12 | return listOf( 13 | cropAndScaleTextImage(GifticonProcessTextTag.GIFTICON_BRAND_NAME, bitmap, 0.23f, 0.83f, 0.96f, 0.94f) 14 | ) 15 | } 16 | 17 | override fun processGifticonImage(bitmap: Bitmap): GifticonProcessImage { 18 | return cropGifticonImage(bitmap, 0.1f, 0.04f, 0.43f, 0.37f) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/giftishow/GiftishowRecognizer.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.giftishow 2 | 3 | import com.lighthouse.util.recognizer.recognizer.TemplateRecognizer 4 | 5 | class GiftishowRecognizer : TemplateRecognizer() { 6 | 7 | override val parser = GiftishowParser() 8 | 9 | override val processor = GiftishowProcessor() 10 | } 11 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/kakao/KakaoParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.kakao 2 | 3 | import com.lighthouse.util.recognizer.parser.BaseParser 4 | 5 | class KakaoParser : BaseParser() { 6 | 7 | override val keywordText = listOf( 8 | "kakaotalk" 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/kakao/KakaoProcessor.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.kakao 2 | 3 | import android.graphics.Bitmap 4 | import com.lighthouse.util.recognizer.processor.BaseProcessor 5 | import com.lighthouse.util.recognizer.processor.GifticonProcessImage 6 | import com.lighthouse.util.recognizer.processor.GifticonProcessText 7 | import com.lighthouse.util.recognizer.processor.GifticonProcessTextTag 8 | 9 | class KakaoProcessor : BaseProcessor() { 10 | 11 | override val enableCenterCrop = true 12 | 13 | override val centerCropAspectRatio = 0.48f 14 | 15 | override fun processTextImage(bitmap: Bitmap): List { 16 | return listOf( 17 | cropAndScaleTextImage(GifticonProcessTextTag.BRAND_GIFTICON_NAME, bitmap, 0f, 0.4f, 0.75f, 0.55f) 18 | ) 19 | } 20 | 21 | override fun processGifticonImage(bitmap: Bitmap): GifticonProcessImage { 22 | return cropGifticonImage(bitmap, 0.13125f, 0.05282f, 0.86875f, 0.41951f) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/kakao/KakaoRecognizer.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.kakao 2 | 3 | import com.lighthouse.util.recognizer.recognizer.TemplateRecognizer 4 | 5 | class KakaoRecognizer : TemplateRecognizer() { 6 | 7 | override val parser = KakaoParser() 8 | 9 | override val processor = KakaoProcessor() 10 | } 11 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/smilecon/SmileConParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.smilecon 2 | 3 | import com.lighthouse.util.recognizer.parser.BaseParser 4 | 5 | class SmileConParser : BaseParser() { 6 | 7 | override val keywordText = listOf( 8 | "스마일콘", 9 | "오피스콘", 10 | "smile" 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/smilecon/SmileConRecognizer.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.smilecon 2 | 3 | import com.lighthouse.util.recognizer.recognizer.TemplateRecognizer 4 | 5 | class SmileConRecognizer : TemplateRecognizer() { 6 | 7 | override val parser = SmileConParser() 8 | 9 | override val processor = SmileConProcessor() 10 | } 11 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/syrup/SyrupParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.syrup 2 | 3 | import com.lighthouse.util.recognizer.parser.BaseParser 4 | 5 | class SyrupParser : BaseParser() { 6 | 7 | override val keywordText = listOf( 8 | "syrup", 9 | "gifticon", 10 | "기프티콘" 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/syrup/SyrupProcessor.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.syrup 2 | 3 | import android.graphics.Bitmap 4 | import com.lighthouse.util.recognizer.processor.BaseProcessor 5 | import com.lighthouse.util.recognizer.processor.GifticonProcessImage 6 | import com.lighthouse.util.recognizer.processor.GifticonProcessText 7 | import com.lighthouse.util.recognizer.processor.GifticonProcessTextTag 8 | 9 | class SyrupProcessor : BaseProcessor() { 10 | 11 | override fun processTextImage(bitmap: Bitmap): List { 12 | return listOf( 13 | cropAndScaleTextImage(GifticonProcessTextTag.GIFTICON_NAME, bitmap, 0.375f, 0.4375f, 0.98437f, 0.52083f), 14 | cropAndScaleTextImage(GifticonProcessTextTag.BRAND_NAME, bitmap, 0.5625f, 0.59375f, 0.98437f, 0.6625f) 15 | ) 16 | } 17 | 18 | override fun processGifticonImage(bitmap: Bitmap): GifticonProcessImage { 19 | return cropGifticonImage(bitmap, 0.0625f, 0.4375f, 0.375f, 0.6458f) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /data/src/main/java/com/lighthouse/util/recognizer/recognizer/syrup/SyrupRecognizer.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.util.recognizer.recognizer.syrup 2 | 3 | import com.lighthouse.util.recognizer.recognizer.TemplateRecognizer 4 | 5 | class SyrupRecognizer : TemplateRecognizer() { 6 | 7 | override val parser = SyrupParser() 8 | 9 | override val processor = SyrupProcessor() 10 | } 11 | -------------------------------------------------------------------------------- /domain/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /domain/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("beep.java.library") 3 | } 4 | 5 | dependencies { 6 | implementation(libs.kotlin.coroutine.core) 7 | implementation(libs.androidX.paging.common.ktx) 8 | implementation(libs.androidX.room.common) 9 | implementation(libs.javax.inject) 10 | 11 | testImplementation(libs.junit4) 12 | testImplementation(libs.junit5.jupiter.params) 13 | testImplementation(libs.junit5.jupiter.engine) 14 | testImplementation(libs.junit5.vintage.engine) 15 | testImplementation(libs.mockk) 16 | testImplementation(libs.google.truth) 17 | testImplementation(libs.kotlin.coroutine.test) 18 | testImplementation(libs.robolectric) 19 | testImplementation(libs.turbine) 20 | } 21 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/BeepError.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | sealed class BeepError( 4 | override val message: String? = null, 5 | override val cause: Throwable? = null 6 | ) : Exception(message, cause) { 7 | 8 | object NetworkFailure : BeepError() 9 | } 10 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/Brand.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | data class Brand( 4 | val name: String, 5 | val count: Int 6 | ) 7 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/BrandPlaceInfo.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | data class BrandPlaceInfo( 4 | val addressName: String, 5 | val placeName: String, 6 | val categoryName: String, 7 | val placeUrl: String, 8 | val brand: String, 9 | val x: String, 10 | val y: String 11 | ) 12 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/DbResult.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | sealed class DbResult { 4 | data class Success(val data: T) : DbResult() 5 | object Loading : DbResult() 6 | object Empty : DbResult() 7 | data class Failure(val throwable: Throwable) : DbResult() 8 | } 9 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/GalleryImage.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | import java.util.Date 4 | 5 | data class GalleryImage( 6 | val id: Long, 7 | val contentUri: String, 8 | val date: Date 9 | ) 10 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/Gifticon.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | import java.util.Date 4 | 5 | data class Gifticon( 6 | val id: String, 7 | val createdAt: Date, 8 | val userId: String, 9 | val hasImage: Boolean, 10 | val croppedUri: String, 11 | val name: String, 12 | val brand: String, 13 | val expireAt: Date, 14 | val barcode: String, 15 | val isCashCard: Boolean, 16 | val balance: Int?, 17 | val memo: String, 18 | val isUsed: Boolean, 19 | ) 20 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/GifticonCrop.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | data class GifticonCrop( 4 | val gifticonId: String, 5 | val rect: Rectangle 6 | ) { 7 | val originPath = "origin$gifticonId" 8 | } 9 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/GifticonForAddition.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | import java.util.Date 4 | 5 | data class GifticonForAddition( 6 | val hasImage: Boolean, 7 | val name: String, 8 | val brandName: String, 9 | val barcode: String, 10 | val expiredAt: Date, 11 | val isCashCard: Boolean, 12 | val balance: Int?, 13 | val originUri: String, 14 | val tempCroppedUri: String, 15 | val croppedRect: Rectangle, 16 | val memo: String, 17 | ) 18 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/GifticonForUpdate.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | import java.util.Date 4 | 5 | data class GifticonForUpdate( 6 | val id: String, 7 | val userId: String, 8 | val hasImage: Boolean, 9 | val name: String, 10 | val brandName: String, 11 | val barcode: String, 12 | val expiredAt: Date, 13 | val isCashCard: Boolean, 14 | val balance: Int?, 15 | val oldCroppedUri: String, 16 | val croppedUri: String, 17 | val croppedRect: Rectangle, 18 | val memo: String, 19 | val isUsed: Boolean, 20 | val createdAt: Date, 21 | ) { 22 | val isUpdatedImage 23 | get() = oldCroppedUri != croppedUri 24 | } 25 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/Rectangle.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | data class Rectangle( 4 | val left: Int, 5 | val top: Int, 6 | val right: Int, 7 | val bottom: Int 8 | ) { 9 | 10 | val width 11 | get() = right - left 12 | 13 | val height 14 | get() = bottom - top 15 | } 16 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/SortBy.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | enum class SortBy { 4 | RECENT, 5 | DEADLINE 6 | } 7 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/model/UserPreferenceOption.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.model 2 | 3 | enum class UserPreferenceOption { 4 | SECURITY, 5 | NOTIFICATION, 6 | GUEST 7 | } 8 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/repository/AuthRepository.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.repository 2 | 3 | interface AuthRepository { 4 | 5 | fun getCurrentUserId(): String 6 | } 7 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/repository/BrandRepository.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.repository 2 | 3 | import com.lighthouse.domain.Dms 4 | import com.lighthouse.domain.model.BrandPlaceInfo 5 | 6 | interface BrandRepository { 7 | 8 | suspend fun getBrandPlaceInfo(brandName: String, x: Dms, y: Dms, size: Int): Result> 9 | suspend fun removeExpirationBrands() 10 | } 11 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/repository/GalleryImageRepository.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.repository 2 | 3 | import androidx.paging.PagingData 4 | import com.lighthouse.domain.model.GalleryImage 5 | import kotlinx.coroutines.flow.Flow 6 | 7 | interface GalleryImageRepository { 8 | fun getImages(pageSize: Int = 10): Flow> 9 | } 10 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/repository/GifticonImageRecognizeRepository.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.repository 2 | 3 | import com.lighthouse.domain.model.GalleryImage 4 | import com.lighthouse.domain.model.GifticonForAddition 5 | import java.util.Date 6 | 7 | interface GifticonImageRecognizeRepository { 8 | 9 | suspend fun recognize(gallery: GalleryImage): GifticonForAddition? 10 | 11 | suspend fun recognizeGifticonName(path: String): String 12 | 13 | suspend fun recognizeBrandName(path: String): String 14 | 15 | suspend fun recognizeBarcode(path: String): String 16 | 17 | suspend fun recognizeBalance(path: String): Int 18 | 19 | suspend fun recognizeExpired(path: String): Date 20 | } 21 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/repository/LocationRepository.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.repository 2 | 3 | import com.lighthouse.domain.VertexLocation 4 | import kotlinx.coroutines.flow.Flow 5 | 6 | interface LocationRepository { 7 | 8 | fun getLocations(): Flow 9 | } 10 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/repository/SecurityRepository.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.repository 2 | 3 | import javax.crypto.Cipher 4 | 5 | interface SecurityRepository { 6 | fun getFingerprintCipher(): Cipher 7 | } 8 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/repository/UserPreferencesRepository.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.repository 2 | 3 | import com.lighthouse.domain.model.UserPreferenceOption 4 | import kotlinx.coroutines.flow.Flow 5 | 6 | interface UserPreferencesRepository { 7 | suspend fun setPinString(pinString: String): Result 8 | fun getPinString(): Flow 9 | 10 | suspend fun setSecurityOption(value: Int): Result 11 | fun getSecurityOption(): Flow 12 | 13 | suspend fun setBooleanOption(option: UserPreferenceOption, value: Boolean): Result 14 | fun getBooleanOption(option: UserPreferenceOption): Flow 15 | 16 | fun isStored(option: UserPreferenceOption): Flow 17 | 18 | suspend fun moveGuestData(uid: String): Result 19 | suspend fun removeCurrentUserData(): Result 20 | } 21 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/GetAllBrandsUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.model.Brand 4 | import com.lighthouse.domain.model.DbResult 5 | import com.lighthouse.domain.repository.AuthRepository 6 | import com.lighthouse.domain.repository.GifticonRepository 7 | import kotlinx.coroutines.flow.Flow 8 | import kotlinx.coroutines.flow.transform 9 | import javax.inject.Inject 10 | 11 | class GetAllBrandsUseCase @Inject constructor( 12 | private val gifticonRepository: GifticonRepository, 13 | authRepository: AuthRepository, 14 | ) { 15 | val userId = authRepository.getCurrentUserId() 16 | 17 | operator fun invoke(): Flow>> { 18 | return gifticonRepository.getAllBrands(userId).transform { 19 | if (it is DbResult.Success) { 20 | emit(DbResult.Success(it.data.sortedByDescending { brand -> brand.count })) 21 | } else { 22 | emit(it) 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/GetBrandPlaceInfosUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.LocationConverter 4 | import com.lighthouse.domain.model.BrandPlaceInfo 5 | import com.lighthouse.domain.repository.BrandRepository 6 | import javax.inject.Inject 7 | 8 | class GetBrandPlaceInfosUseCase @Inject constructor( 9 | private val brandRepository: BrandRepository 10 | ) { 11 | 12 | suspend operator fun invoke( 13 | brandNames: List, 14 | x: Double, 15 | y: Double, 16 | size: Int 17 | ): Result> { 18 | val cardinalLocations = LocationConverter.getCardinalDirections(x, y) 19 | 20 | return runCatching { 21 | cardinalLocations.flatMap { location -> 22 | brandNames.flatMap { brandName -> 23 | brandRepository.getBrandPlaceInfo(brandName, location.x, location.y, size).getOrThrow() 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/GetFilteredGifticonsUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.model.DbResult 4 | import com.lighthouse.domain.model.Gifticon 5 | import com.lighthouse.domain.model.SortBy 6 | import com.lighthouse.domain.repository.AuthRepository 7 | import com.lighthouse.domain.repository.GifticonRepository 8 | import kotlinx.coroutines.flow.Flow 9 | import javax.inject.Inject 10 | 11 | class GetFilteredGifticonsUseCase @Inject constructor( 12 | private val gifticonRepository: GifticonRepository, 13 | authRepository: AuthRepository 14 | ) { 15 | val userId = authRepository.getCurrentUserId() 16 | 17 | operator fun invoke(filter: Set, sortBy: SortBy = SortBy.DEADLINE): Flow>> { 18 | return if (filter.isEmpty()) { 19 | gifticonRepository.getAllGifticons(userId, sortBy) 20 | } else { 21 | gifticonRepository.getFilteredGifticons(userId, filter, sortBy) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/GetFingerprintCipherUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.repository.SecurityRepository 4 | import javax.crypto.Cipher 5 | import javax.inject.Inject 6 | 7 | class GetFingerprintCipherUseCase @Inject constructor( 8 | private val securityRepository: SecurityRepository 9 | ) { 10 | 11 | operator fun invoke(): Cipher { 12 | return securityRepository.getFingerprintCipher() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/GetGifticonUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.model.DbResult 4 | import com.lighthouse.domain.model.Gifticon 5 | import com.lighthouse.domain.repository.GifticonRepository 6 | import kotlinx.coroutines.flow.Flow 7 | import javax.inject.Inject 8 | 9 | class GetGifticonUseCase @Inject constructor( 10 | private val gifticonRepository: GifticonRepository 11 | ) { 12 | 13 | operator fun invoke(id: String): Flow> { 14 | return gifticonRepository.getGifticon(id) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/GetHistoryUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.model.DbResult 4 | import com.lighthouse.domain.model.History 5 | import com.lighthouse.domain.repository.GifticonRepository 6 | import kotlinx.coroutines.flow.Flow 7 | import javax.inject.Inject 8 | 9 | class GetHistoryUseCase @Inject constructor( 10 | val repository: GifticonRepository, 11 | ) { 12 | operator fun invoke(gifticonId: String): Flow>> { 13 | return repository.getHistory(gifticonId) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/GetSharedDateUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import java.util.Date 4 | 5 | class GetSharedDateUseCase { 6 | 7 | operator fun invoke(id: String): Date? { 8 | return null 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/GetUserLocationUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.repository.LocationRepository 4 | import javax.inject.Inject 5 | 6 | class GetUserLocationUseCase @Inject constructor( 7 | private val repository: LocationRepository 8 | ) { 9 | 10 | operator fun invoke() = repository.getLocations() 11 | } 12 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/HasVariableGifticonUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.repository.AuthRepository 4 | import com.lighthouse.domain.repository.GifticonRepository 5 | import kotlinx.coroutines.flow.Flow 6 | import javax.inject.Inject 7 | 8 | class HasVariableGifticonUseCase @Inject constructor( 9 | private val gifticonRepository: GifticonRepository, 10 | authRepository: AuthRepository 11 | ) { 12 | 13 | val userId = authRepository.getCurrentUserId() 14 | 15 | operator fun invoke(): Flow { 16 | return gifticonRepository.hasUsableGifticon(userId) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/MoveUserIdGifticonUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.repository.GifticonRepository 4 | import javax.inject.Inject 5 | 6 | class MoveUserIdGifticonUseCase @Inject constructor( 7 | private val gifticonRepository: GifticonRepository 8 | ) { 9 | suspend operator fun invoke(oldUserId: String, newUserId: String) { 10 | gifticonRepository.moveUserIdGifticon(oldUserId, newUserId) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/RemoveExpirationBrandUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.repository.BrandRepository 4 | import javax.inject.Inject 5 | 6 | class RemoveExpirationBrandUseCase @Inject constructor( 7 | private val brandRepository: BrandRepository 8 | ) { 9 | 10 | suspend operator fun invoke() { 11 | brandRepository.removeExpirationBrands() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/RemoveGifticonUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.repository.GifticonRepository 4 | import javax.inject.Inject 5 | 6 | class RemoveGifticonUseCase @Inject constructor( 7 | private val gifticonRepository: GifticonRepository 8 | ) { 9 | 10 | suspend operator fun invoke(gifticonId: String) { 11 | gifticonRepository.removeGifticon(gifticonId) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/ResetHistoryButInitUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.repository.GifticonRepository 4 | import javax.inject.Inject 5 | 6 | class ResetHistoryButInitUseCase @Inject constructor( 7 | private val repository: GifticonRepository, 8 | ) { 9 | suspend operator fun invoke(gifticonId: String) { 10 | repository.resetHistoryButInit(gifticonId) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/UnUseGifticonUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.repository.GifticonRepository 4 | import javax.inject.Inject 5 | 6 | class UnUseGifticonUseCase @Inject constructor( 7 | private val gifticonRepository: GifticonRepository 8 | ) { 9 | suspend operator fun invoke(gifticonId: String) { 10 | gifticonRepository.unUseGifticon(gifticonId) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/UpdateSharedDateUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | class UpdateSharedDateUseCase { 4 | 5 | operator fun invoke(id: String): Result { 6 | return Result.success(Unit) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/UseCashCardGifticonUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.model.History 4 | import com.lighthouse.domain.repository.GifticonRepository 5 | import com.lighthouse.domain.util.currentTime 6 | import kotlinx.coroutines.flow.first 7 | import javax.inject.Inject 8 | 9 | class UseCashCardGifticonUseCase @Inject constructor( 10 | private val gifticonRepository: GifticonRepository, 11 | private val getUserLocationUseCase: GetUserLocationUseCase, 12 | ) { 13 | 14 | suspend operator fun invoke(gifticonId: String, amount: Int, hasLocationPermission: Boolean) { 15 | val userLocation = if (hasLocationPermission) getUserLocationUseCase().first() else null 16 | val history = History.UseCashCard(currentTime, gifticonId, amount, null, userLocation) 17 | 18 | gifticonRepository.useCashCardGifticon(gifticonId, amount, history) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/UseGifticonUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase 2 | 3 | import com.lighthouse.domain.model.History 4 | import com.lighthouse.domain.repository.GifticonRepository 5 | import com.lighthouse.domain.util.currentTime 6 | import kotlinx.coroutines.flow.first 7 | import javax.inject.Inject 8 | 9 | class UseGifticonUseCase @Inject constructor( 10 | private val gifticonRepository: GifticonRepository, 11 | private val getUserLocationUseCase: GetUserLocationUseCase, 12 | ) { 13 | suspend operator fun invoke(gifticonId: String, hasLocationPermission: Boolean) { 14 | val userLocation = if (hasLocationPermission) getUserLocationUseCase().first() else null 15 | val history = History.Use(currentTime, gifticonId, userLocation) 16 | 17 | gifticonRepository.useGifticon(gifticonId, history) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/HasGifticonBrandUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit 2 | 3 | import com.lighthouse.domain.repository.GifticonRepository 4 | import javax.inject.Inject 5 | 6 | class HasGifticonBrandUseCase @Inject constructor( 7 | private val gifticonRepository: GifticonRepository 8 | ) { 9 | suspend operator fun invoke(brand: String): Boolean { 10 | return gifticonRepository.hasGifticonBrand(brand) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/RecognizeBalanceUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit 2 | 3 | import com.lighthouse.domain.repository.GifticonImageRecognizeRepository 4 | import javax.inject.Inject 5 | 6 | class RecognizeBalanceUseCase @Inject constructor( 7 | private val gifticonImageRecognizeRepository: GifticonImageRecognizeRepository 8 | ) { 9 | 10 | suspend operator fun invoke(uri: String): Int { 11 | return gifticonImageRecognizeRepository.recognizeBalance(uri) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/RecognizeBarcodeUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit 2 | 3 | import com.lighthouse.domain.repository.GifticonImageRecognizeRepository 4 | import javax.inject.Inject 5 | 6 | class RecognizeBarcodeUseCase @Inject constructor( 7 | private val gifticonImageRecognizeRepository: GifticonImageRecognizeRepository 8 | ) { 9 | 10 | suspend operator fun invoke(uri: String): String { 11 | return gifticonImageRecognizeRepository.recognizeBarcode(uri) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/RecognizeBrandNameUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit 2 | 3 | import com.lighthouse.domain.repository.GifticonImageRecognizeRepository 4 | import javax.inject.Inject 5 | 6 | class RecognizeBrandNameUseCase @Inject constructor( 7 | private val gifticonImageRecognizeRepository: GifticonImageRecognizeRepository 8 | ) { 9 | 10 | suspend operator fun invoke(uri: String): String { 11 | return gifticonImageRecognizeRepository.recognizeBrandName(uri) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/RecognizeExpiredUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit 2 | 3 | import com.lighthouse.domain.repository.GifticonImageRecognizeRepository 4 | import java.util.Date 5 | import javax.inject.Inject 6 | 7 | class RecognizeExpiredUseCase @Inject constructor( 8 | private val gifticonImageRecognizeRepository: GifticonImageRecognizeRepository 9 | ) { 10 | 11 | suspend operator fun invoke(uri: String): Date { 12 | return gifticonImageRecognizeRepository.recognizeExpired(uri) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/RecognizeGifticonImageUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit 2 | 3 | import com.lighthouse.domain.model.GalleryImage 4 | import com.lighthouse.domain.model.GifticonForAddition 5 | import com.lighthouse.domain.repository.GifticonImageRecognizeRepository 6 | import javax.inject.Inject 7 | 8 | class RecognizeGifticonImageUseCase @Inject constructor( 9 | private val gifticonImageRecognizeRepository: GifticonImageRecognizeRepository 10 | ) { 11 | 12 | suspend operator fun invoke(galleryImage: GalleryImage): GifticonForAddition? { 13 | return gifticonImageRecognizeRepository.recognize(galleryImage) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/RecognizeGifticonNameUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit 2 | 3 | import com.lighthouse.domain.repository.GifticonImageRecognizeRepository 4 | import javax.inject.Inject 5 | 6 | class RecognizeGifticonNameUseCase @Inject constructor( 7 | private val gifticonImageRecognizeRepository: GifticonImageRecognizeRepository 8 | ) { 9 | 10 | suspend operator fun invoke(uri: String): String { 11 | return gifticonImageRecognizeRepository.recognizeGifticonName(uri) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/addgifticon/SaveGifticonsUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit.addgifticon 2 | 3 | import com.lighthouse.domain.model.GifticonForAddition 4 | import com.lighthouse.domain.repository.AuthRepository 5 | import com.lighthouse.domain.repository.GifticonRepository 6 | import javax.inject.Inject 7 | 8 | class SaveGifticonsUseCase @Inject constructor( 9 | private val gifticonRepository: GifticonRepository, 10 | private val authRepository: AuthRepository 11 | ) { 12 | 13 | suspend operator fun invoke(gifticons: List) { 14 | gifticonRepository.saveGifticons(authRepository.getCurrentUserId(), gifticons) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/modifygifticon/GetGifticonForUpdateUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit.modifygifticon 2 | 3 | import com.lighthouse.domain.model.GifticonForUpdate 4 | import com.lighthouse.domain.repository.AuthRepository 5 | import com.lighthouse.domain.repository.GifticonRepository 6 | import javax.inject.Inject 7 | 8 | class GetGifticonForUpdateUseCase @Inject constructor( 9 | private val gifticonRepository: GifticonRepository, 10 | private val authRepository: AuthRepository 11 | ) { 12 | 13 | suspend operator fun invoke(id: String): GifticonForUpdate? { 14 | return gifticonRepository.getGifticonCrop(authRepository.getCurrentUserId(), id) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/edit/modifygifticon/ModifyGifticonUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.edit.modifygifticon 2 | 3 | import com.lighthouse.domain.model.GifticonForUpdate 4 | import com.lighthouse.domain.repository.AuthRepository 5 | import com.lighthouse.domain.repository.GifticonRepository 6 | import javax.inject.Inject 7 | 8 | class ModifyGifticonUseCase @Inject constructor( 9 | private val gifticonRepository: GifticonRepository, 10 | private val authRepository: AuthRepository 11 | ) { 12 | 13 | suspend operator fun invoke(gifticonForUpdate: GifticonForUpdate) { 14 | if (authRepository.getCurrentUserId() == gifticonForUpdate.userId) { 15 | gifticonRepository.updateGifticon(gifticonForUpdate) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/gallery/GetGalleryImagesUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.gallery 2 | 3 | import androidx.paging.PagingData 4 | import com.lighthouse.domain.model.GalleryImage 5 | import com.lighthouse.domain.repository.GalleryImageRepository 6 | import kotlinx.coroutines.flow.Flow 7 | import javax.inject.Inject 8 | 9 | class GetGalleryImagesUseCase @Inject constructor( 10 | private val galleryImageRepository: GalleryImageRepository 11 | ) { 12 | 13 | operator fun invoke(): Flow> { 14 | return galleryImageRepository.getImages() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/GetCorrespondWithPinUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.repository.UserPreferencesRepository 4 | import kotlinx.coroutines.flow.first 5 | import javax.inject.Inject 6 | 7 | class GetCorrespondWithPinUseCase @Inject constructor( 8 | private val userPreferencesRepository: UserPreferencesRepository 9 | ) { 10 | 11 | suspend operator fun invoke(pinString: String): Boolean { 12 | val correctPinString = userPreferencesRepository.getPinString() 13 | return pinString == correctPinString.first() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/GetGuestOptionUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.model.UserPreferenceOption 4 | import com.lighthouse.domain.repository.UserPreferencesRepository 5 | import kotlinx.coroutines.flow.Flow 6 | import javax.inject.Inject 7 | 8 | class GetGuestOptionUseCase @Inject constructor( 9 | private val userPreferencesRepository: UserPreferencesRepository 10 | ) { 11 | operator fun invoke(): Flow { 12 | return userPreferencesRepository.getBooleanOption(UserPreferenceOption.GUEST) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/GetNotificationOptionUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.model.UserPreferenceOption 4 | import com.lighthouse.domain.repository.UserPreferencesRepository 5 | import kotlinx.coroutines.flow.Flow 6 | import javax.inject.Inject 7 | 8 | class GetNotificationOptionUseCase @Inject constructor( 9 | private val userPreferencesRepository: UserPreferencesRepository 10 | ) { 11 | operator fun invoke(): Flow { 12 | return userPreferencesRepository.getBooleanOption(UserPreferenceOption.NOTIFICATION) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/GetOptionStoredUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.model.UserPreferenceOption 4 | import com.lighthouse.domain.repository.UserPreferencesRepository 5 | import kotlinx.coroutines.flow.Flow 6 | import javax.inject.Inject 7 | 8 | class GetOptionStoredUseCase @Inject constructor( 9 | private val userPreferencesRepository: UserPreferencesRepository 10 | ) { 11 | operator fun invoke(option: UserPreferenceOption): Flow { 12 | return userPreferencesRepository.isStored(option) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/GetSecurityOptionUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.repository.UserPreferencesRepository 4 | import kotlinx.coroutines.flow.Flow 5 | import javax.inject.Inject 6 | 7 | class GetSecurityOptionUseCase @Inject constructor( 8 | private val userPreferencesRepository: UserPreferencesRepository 9 | ) { 10 | operator fun invoke(): Flow { 11 | return userPreferencesRepository.getSecurityOption() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/MoveGuestDataUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.repository.UserPreferencesRepository 4 | import javax.inject.Inject 5 | 6 | class MoveGuestDataUseCase @Inject constructor( 7 | private val userPreferencesRepository: UserPreferencesRepository 8 | ) { 9 | suspend operator fun invoke(uid: String): Result { 10 | return userPreferencesRepository.moveGuestData(uid) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/RemoveUserDataUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.repository.UserPreferencesRepository 4 | import javax.inject.Inject 5 | 6 | class RemoveUserDataUseCase @Inject constructor( 7 | private val userPreferencesRepository: UserPreferencesRepository 8 | ) { 9 | suspend operator fun invoke(): Result { 10 | return userPreferencesRepository.removeCurrentUserData() 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/SaveGuestOptionUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.model.UserPreferenceOption 4 | import com.lighthouse.domain.repository.UserPreferencesRepository 5 | import javax.inject.Inject 6 | 7 | class SaveGuestOptionUseCase @Inject constructor( 8 | private val userPreferencesRepository: UserPreferencesRepository 9 | ) { 10 | suspend operator fun invoke(option: Boolean): Result { 11 | return userPreferencesRepository.setBooleanOption(UserPreferenceOption.GUEST, option) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/SaveNotificationOptionUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.model.UserPreferenceOption 4 | import com.lighthouse.domain.repository.UserPreferencesRepository 5 | import javax.inject.Inject 6 | 7 | class SaveNotificationOptionUseCase @Inject constructor( 8 | private val userPreferencesRepository: UserPreferencesRepository 9 | ) { 10 | 11 | suspend operator fun invoke(option: Boolean): Result { 12 | return userPreferencesRepository.setBooleanOption(UserPreferenceOption.NOTIFICATION, option) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/SavePinUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.repository.UserPreferencesRepository 4 | import javax.inject.Inject 5 | 6 | class SavePinUseCase @Inject constructor( 7 | private val userPreferencesRepository: UserPreferencesRepository 8 | ) { 9 | 10 | suspend operator fun invoke(pinString: String): Result { 11 | return userPreferencesRepository.setPinString(pinString) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/usecase/setting/SaveSecurityOptionUseCase.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.usecase.setting 2 | 3 | import com.lighthouse.domain.repository.UserPreferencesRepository 4 | import javax.inject.Inject 5 | 6 | class SaveSecurityOptionUseCase @Inject constructor( 7 | private val userPreferencesRepository: UserPreferencesRepository 8 | ) { 9 | suspend operator fun invoke(option: Int) { 10 | userPreferencesRepository.setSecurityOption(option) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /domain/src/main/java/com/lighthouse/domain/util/DateTime.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.domain.util 2 | 3 | import java.util.Calendar 4 | import java.util.Date 5 | 6 | val today: Date 7 | get() = Date().adjust() 8 | 9 | val currentTime: Date 10 | get() = Calendar.getInstance().time 11 | 12 | /** 13 | * 현재 Date 가 과거 일자인지 계산한다 14 | */ 15 | fun Date.isExpired(): Boolean = this@isExpired.adjust().time < today.time 16 | 17 | /** 18 | * 현재 Date 의 디데이를 계산한다 19 | */ 20 | fun Date.calcDday(): Int = ((this@calcDday.adjust() - today).time / (1000 * 60 * 60 * 24)).toInt() 21 | 22 | operator fun Date.minus(other: Date): Date = Date(this@minus.time - other.time) 23 | 24 | /** 25 | * Date 의 시, 분, 초를 0 으로 설정한다 26 | */ 27 | fun Date.adjust(): Date = Calendar.getInstance().apply { 28 | time = this@adjust 29 | set(Calendar.HOUR_OF_DAY, 0) 30 | set(Calendar.MINUTE, 0) 31 | set(Calendar.SECOND, 0) 32 | set(Calendar.MILLISECOND, 0) 33 | }.time 34 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Feb 05 00:10:25 KST 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /presentation/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /google-services.json 3 | -------------------------------------------------------------------------------- /presentation/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/consumer-rules.pro -------------------------------------------------------------------------------- /presentation/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.kts. 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 -------------------------------------------------------------------------------- /presentation/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/adapter/BindableAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.adapter 2 | 3 | interface BindableAdapter { 4 | 5 | fun setData(data: T, commitCallback: () -> Unit = {}) 6 | } 7 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/adapter/BindableListAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.adapter 2 | 3 | import androidx.recyclerview.widget.DiffUtil 4 | import androidx.recyclerview.widget.ListAdapter 5 | import androidx.recyclerview.widget.RecyclerView 6 | 7 | abstract class BindableListAdapter(diffCallback: DiffUtil.ItemCallback) : 8 | ListAdapter(diffCallback), 9 | BindableAdapter> { 10 | 11 | override fun setData(data: List, commitCallback: () -> Unit) { 12 | submitList(data, commitCallback) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/background/ExpirationBrandWorker.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.background 2 | 3 | import android.content.Context 4 | import androidx.hilt.work.HiltWorker 5 | import androidx.work.CoroutineWorker 6 | import androidx.work.WorkerParameters 7 | import com.lighthouse.domain.usecase.RemoveExpirationBrandUseCase 8 | import dagger.assisted.Assisted 9 | import dagger.assisted.AssistedInject 10 | 11 | @HiltWorker 12 | class ExpirationBrandWorker @AssistedInject constructor( 13 | @Assisted context: Context, 14 | @Assisted workerParams: WorkerParameters, 15 | private val removeExpirationBrandUseCase: RemoveExpirationBrandUseCase 16 | ) : CoroutineWorker(context, workerParams) { 17 | 18 | override suspend fun doWork(): Result { 19 | runCatching { removeExpirationBrandUseCase } 20 | .onSuccess { 21 | return Result.success() 22 | } 23 | .onFailure { 24 | return Result.failure() 25 | } 26 | return Result.retry() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/binding/Layout.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.binding 2 | 3 | import androidx.core.view.isVisible 4 | import androidx.databinding.BindingAdapter 5 | import com.facebook.shimmer.ShimmerFrameLayout 6 | 7 | @BindingAdapter("setShimmerState") 8 | fun setShimmerState(layout: ShimmerFrameLayout, state: Boolean) { 9 | layout.isVisible = state 10 | 11 | when (state) { 12 | true -> layout.startShimmer() 13 | false -> layout.stopShimmer() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/binding/RecyclerView.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.binding 2 | 3 | import androidx.databinding.BindingAdapter 4 | import androidx.recyclerview.widget.RecyclerView 5 | import androidx.viewpager2.widget.ViewPager2 6 | import com.lighthouse.presentation.adapter.BindableAdapter 7 | 8 | @BindingAdapter("setItems") 9 | fun setItems(view: RecyclerView, data: T?) { 10 | data ?: return 11 | when (val listAdapter = view.adapter) { 12 | is BindableAdapter<*> -> { 13 | (listAdapter as BindableAdapter).setData(data) { 14 | view.invalidateItemDecorations() 15 | } 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/binding/TextInputLayout.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.binding 2 | 3 | import androidx.databinding.BindingAdapter 4 | import com.google.android.material.textfield.TextInputLayout 5 | import com.lighthouse.presentation.R 6 | 7 | @BindingAdapter("concurrencySuffixText") 8 | fun applySuffixTextOrNull(view: TextInputLayout, text: String) { 9 | view.suffixText = if (text.isNotBlank()) view.context.getString(R.string.all_cash_origin_unit) else null 10 | } 11 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/extension/Bitmap.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.extension 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.Matrix 5 | 6 | fun Bitmap.rotated(degrees: Float): Bitmap { 7 | val matrix = Matrix().apply { postRotate(degrees) } 8 | return Bitmap.createBitmap(this, 0, 0, width, height, matrix, false) 9 | } 10 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/extension/Bundle.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.extension 2 | 3 | import android.os.Build 4 | import android.os.Bundle 5 | import android.os.Parcelable 6 | 7 | fun Bundle.getParcelableArrayListCompat(key: String, clazz: Class): ArrayList? { 8 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { 9 | getParcelableArrayList(key, clazz) 10 | } else { 11 | getParcelableArrayList(key) 12 | } 13 | } 14 | 15 | fun Bundle.getParcelableCompat(key: String, clazz: Class): T? { 16 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { 17 | getParcelable(key, clazz) 18 | } else { 19 | getParcelable(key) as? T 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/extension/ContentResolver.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.extension 2 | 3 | import android.content.ContentResolver 4 | import android.content.ContentResolver.SCHEME_CONTENT 5 | import android.graphics.Bitmap 6 | import android.graphics.ImageDecoder 7 | import android.net.Uri 8 | import android.os.Build 9 | import android.provider.MediaStore 10 | import java.io.IOException 11 | 12 | fun ContentResolver.getBitmap(uri: Uri): Bitmap? { 13 | if (uri.scheme != SCHEME_CONTENT) { 14 | return null 15 | } 16 | return try { 17 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 18 | val source = ImageDecoder.createSource(this, uri) 19 | ImageDecoder.decodeBitmap(source) { decoder, _, _ -> 20 | decoder.isMutableRequired = true 21 | } 22 | } else { 23 | MediaStore.Images.Media.getBitmap(this, uri) 24 | } 25 | } catch (e: IOException) { 26 | null 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/extension/DialogFragment.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.extension 2 | 3 | import androidx.fragment.app.DialogFragment 4 | import androidx.fragment.app.FragmentManager 5 | 6 | fun DialogFragment.show(fragmentManager: FragmentManager) { 7 | show(fragmentManager, javaClass.name) 8 | } 9 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/extension/Intent.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.extension 2 | 3 | import android.content.Intent 4 | import android.os.Parcelable 5 | 6 | fun Intent.getParcelableArrayList(key: String, clazz: Class): ArrayList? { 7 | return extras?.getParcelableArrayListCompat(key, clazz) 8 | } 9 | 10 | fun Intent.getParcelable(key: String, clazz: Class): T? { 11 | return extras?.getParcelableCompat(key, clazz) 12 | } 13 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/extension/LifecycleOwner.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.extension 2 | 3 | import androidx.lifecycle.Lifecycle 4 | import androidx.lifecycle.LifecycleOwner 5 | import androidx.lifecycle.lifecycleScope 6 | import androidx.lifecycle.repeatOnLifecycle 7 | import kotlinx.coroutines.CoroutineScope 8 | import kotlinx.coroutines.launch 9 | 10 | fun LifecycleOwner.repeatOnStarted(block: suspend (CoroutineScope) -> Unit) { 11 | lifecycleScope.launch { 12 | repeatOnLifecycle(Lifecycle.State.STARTED) { 13 | block(this) 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/extension/ScrollView.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.extension 2 | 3 | import android.view.View 4 | import android.widget.ScrollView 5 | 6 | fun ScrollView.scrollToBottom() { 7 | this.post { 8 | this.fullScroll(View.FOCUS_DOWN) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/extension/View.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.extension 2 | 3 | import android.view.View 4 | 5 | fun View.isOnScreen(): Boolean { 6 | val viewLocation = IntArray(2) 7 | getLocationOnScreen(viewLocation) 8 | 9 | return viewLocation[0] in 0..screenWidth && viewLocation[1] in 0..screenHeight 10 | } 11 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/mapper/BrandPlaceInfoUiModelMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.mapper 2 | 3 | import com.lighthouse.domain.model.BrandPlaceInfo 4 | import com.lighthouse.presentation.model.BrandPlaceInfoUiModel 5 | 6 | fun List.toPresentation(): List = map { 7 | BrandPlaceInfoUiModel( 8 | addressName = it.addressName, 9 | placeName = it.placeName, 10 | categoryName = it.categoryName, 11 | placeUrl = it.placeUrl, 12 | brand = it.brand, 13 | x = it.x, 14 | y = it.y 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/mapper/GalleryImageMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.mapper 2 | 3 | import android.net.Uri 4 | import com.lighthouse.domain.model.GalleryImage 5 | import com.lighthouse.presentation.extension.toString 6 | import com.lighthouse.presentation.model.GalleryUIModel 7 | 8 | fun GalleryImage.toPresentation(index: Int = -1): GalleryUIModel.Gallery = GalleryUIModel.Gallery( 9 | id = id, 10 | uri = Uri.parse(contentUri), 11 | selectedOrder = index, 12 | createdDate = date.toString("yyyy-MM-dd") 13 | ) 14 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/mapper/GifticonSortByMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.mapper 2 | 3 | import com.lighthouse.domain.model.SortBy 4 | import com.lighthouse.presentation.model.GifticonSortBy 5 | 6 | fun GifticonSortBy.toDomain(): SortBy { 7 | return when (this) { 8 | GifticonSortBy.RECENT -> SortBy.RECENT 9 | GifticonSortBy.DEADLINE -> SortBy.DEADLINE 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/mapper/ModifyGifticonUIModelMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.mapper 2 | 3 | import androidx.core.graphics.toRect 4 | import com.lighthouse.domain.model.GifticonForUpdate 5 | import com.lighthouse.presentation.extension.toDigit 6 | import com.lighthouse.presentation.model.ModifyGifticonUIModel 7 | 8 | fun ModifyGifticonUIModel.toDomain(): GifticonForUpdate { 9 | return GifticonForUpdate( 10 | id = id, 11 | userId = userId, 12 | hasImage = hasImage, 13 | oldCroppedUri = oldCroppedUri.toString(), 14 | croppedUri = croppedUri.toString(), 15 | croppedRect = croppedRect.toRect().toDomain(), 16 | name = name, 17 | brandName = brandName, 18 | barcode = barcode, 19 | expiredAt = expiredAt, 20 | isCashCard = isCashCard, 21 | balance = balance.toDigit(), 22 | memo = memo, 23 | isUsed = isUsed, 24 | createdAt = createdAt 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/mapper/RectMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.mapper 2 | 3 | import android.graphics.Rect 4 | import com.lighthouse.domain.model.Rectangle 5 | 6 | fun Rect.toDomain(): Rectangle { 7 | return Rectangle(left, top, right, bottom) 8 | } 9 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/mapper/RectangleMapper.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.mapper 2 | 3 | import android.graphics.Rect 4 | import com.lighthouse.domain.model.Rectangle 5 | 6 | fun Rectangle.toPresentation(): Rect { 7 | return Rect(left, top, right, bottom) 8 | } 9 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/AddGifticonUIModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import android.graphics.RectF 4 | import android.net.Uri 5 | import java.util.Date 6 | 7 | data class AddGifticonUIModel( 8 | val id: Long, 9 | val origin: Uri, 10 | val hasImage: Boolean, 11 | val name: String, 12 | val nameRectF: RectF, 13 | val brandName: String, 14 | val brandNameRectF: RectF, 15 | val approveBrandName: String, 16 | val barcode: String, 17 | val barcodeRectF: RectF, 18 | val expiredAt: Date, 19 | val expiredAtRectF: RectF, 20 | val approveExpiredAt: Boolean, 21 | val isCashCard: Boolean, 22 | val balance: String, 23 | val balanceRectF: RectF, 24 | val memo: String, 25 | val gifticonImage: CroppedImage, 26 | val approveGifticonImage: Boolean, 27 | val createdDate: String 28 | ) { 29 | val uri: Uri 30 | get() = gifticonImage.uri ?: origin 31 | } 32 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/BrandPlaceInfoUiModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import java.io.Serializable 4 | 5 | data class BrandPlaceInfoUiModel( 6 | val addressName: String, 7 | val placeName: String, 8 | val categoryName: String, 9 | val placeUrl: String, 10 | val brand: String, 11 | val x: String, 12 | val y: String 13 | ) : Serializable { 14 | 15 | val brandLowerName = brand.lowercase() 16 | } 17 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/CashAmountPreset.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import android.content.Context 4 | import com.lighthouse.presentation.R 5 | import com.lighthouse.presentation.extension.toConcurrency 6 | 7 | enum class CashAmountPreset(val amount: Int?) { 8 | ONE(1000), TWO(5000), THREE(10000), TOTAL(null); 9 | 10 | fun toString(context: Context): String { 11 | return amount?.toConcurrency(context) 12 | ?: context.resources.getString(R.string.use_gifticon_dialog_chip_total_amount) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/CroppedImage.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import android.graphics.RectF 4 | import android.net.Uri 5 | 6 | data class CroppedImage( 7 | val uri: Uri? = null, 8 | val croppedRect: RectF = RectF() 9 | ) 10 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/GalleryUIModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import android.net.Uri 4 | import android.os.Parcelable 5 | import kotlinx.parcelize.Parcelize 6 | 7 | sealed class GalleryUIModel { 8 | data class Header(val date: String) : GalleryUIModel() 9 | 10 | @Parcelize 11 | data class Gallery( 12 | val id: Long, 13 | val uri: Uri, 14 | val selectedOrder: Int, 15 | val createdDate: String 16 | ) : GalleryUIModel(), Parcelable 17 | } 18 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/GifticonSortBy.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import androidx.annotation.StringRes 4 | import com.lighthouse.presentation.R 5 | 6 | enum class GifticonSortBy(@StringRes val stringRes: Int) { 7 | RECENT(R.string.gifticon_list_sort_by_recent), 8 | DEADLINE(R.string.gifticon_list_sort_by_deadline) 9 | } 10 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/GifticonUIModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import android.net.Uri 4 | import java.io.Serializable 5 | import java.util.Date 6 | 7 | data class GifticonUIModel( 8 | val id: String, 9 | val hasImage: Boolean, 10 | val croppedUri: Uri?, 11 | val name: String, 12 | val brand: String, 13 | val expireAt: Date, 14 | val barcode: String, 15 | val isCashCard: Boolean, 16 | val balance: Int?, 17 | val memo: String, 18 | val isUsed: Boolean, 19 | ) : Serializable { 20 | 21 | val originPath = "origin$id" 22 | val brandLowerName = brand.lowercase() 23 | } 24 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/GifticonWithDistanceUIModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import android.net.Uri 4 | import java.util.Date 5 | 6 | data class GifticonWithDistanceUIModel( 7 | val id: String, 8 | val userId: String, 9 | val hasImage: Boolean, 10 | val croppedUri: Uri, 11 | val name: String, 12 | val brand: String, 13 | val expireAt: Date, 14 | val balance: Int?, 15 | val isUsed: Boolean, 16 | val distance: Int, 17 | ) 18 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/HistoryUiModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import com.lighthouse.presentation.util.resource.UIText 4 | import java.util.Date 5 | 6 | sealed class HistoryUiModel { 7 | data class Header(val date: String) : HistoryUiModel() 8 | 9 | data class History( 10 | val date: Date, 11 | val type: UIText, 12 | val gifticonName: String, 13 | val amount: UIText, 14 | val balance: UIText, 15 | val location: LocationUiModel?, 16 | ) : HistoryUiModel() 17 | } 18 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/LocationUiModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import com.lighthouse.domain.VertexLocation 4 | 5 | data class LocationUiModel( 6 | val location: VertexLocation, 7 | val displayText: String, 8 | ) 9 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/model/ModifyGifticonUIModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.model 2 | 3 | import android.graphics.RectF 4 | import android.net.Uri 5 | import java.util.Date 6 | 7 | data class ModifyGifticonUIModel( 8 | val id: String, 9 | val userId: String, 10 | val hasImage: Boolean, 11 | val oldCroppedUri: Uri, 12 | val croppedUri: Uri, 13 | val croppedRect: RectF, 14 | val name: String, 15 | val nameRectF: RectF, 16 | val brandName: String, 17 | val brandNameRectF: RectF, 18 | val approveBrandName: String, 19 | val barcode: String, 20 | val barcodeRectF: RectF, 21 | val expiredAt: Date, 22 | val expiredAtRectF: RectF, 23 | val approveExpiredAt: Boolean, 24 | val isCashCard: Boolean, 25 | val balance: String, 26 | val balanceRectF: RectF, 27 | val memo: String, 28 | val isUsed: Boolean, 29 | val createdAt: Date 30 | ) { 31 | val originFileName = "origin$id" 32 | } 33 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/common/GifticonViewHolderType.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.common 2 | 3 | enum class GifticonViewHolderType { 4 | VERTICAL, 5 | HORIZONTAL 6 | } 7 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/common/UiState.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.common 2 | 3 | sealed class UiState { 4 | object Loading : UiState() 5 | data class Success(val item: T) : UiState() 6 | object NetworkFailure : UiState() 7 | object NotFoundResults : UiState() 8 | object Failure : UiState() 9 | } 10 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/common/dialog/datepicker/OnDatePickListener.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.common.dialog.datepicker 2 | 3 | interface OnDatePickListener { 4 | fun onDatePick(year: Int, month: Int, date: Int) 5 | } 6 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/cropgifticon/event/CropGifticonEvent.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.cropgifticon.event 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.RectF 5 | import com.lighthouse.presentation.util.resource.UIText 6 | 7 | sealed class CropGifticonEvent { 8 | 9 | object PopupBackStack : CropGifticonEvent() 10 | object RequestCrop : CropGifticonEvent() 11 | data class CompleteCrop(val croppedBitmap: Bitmap, val croppedRect: RectF) : CropGifticonEvent() 12 | data class ShowSnackBar(val uiText: UIText) : CropGifticonEvent() 13 | } 14 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/cropgifticon/view/CropImageInfo.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.cropgifticon.view 2 | 3 | import android.graphics.RectF 4 | import android.net.Uri 5 | 6 | data class CropImageInfo(val uri: Uri?, val croppedRect: RectF?) 7 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/cropgifticon/view/CropImageMode.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.cropgifticon.view 2 | 3 | enum class CropImageMode { 4 | DRAW_PEN, 5 | DRAG_WINDOW, 6 | } 7 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/cropgifticon/view/OnChangeCropRectListener.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.cropgifticon.view 2 | 3 | import android.graphics.RectF 4 | 5 | interface OnChangeCropRectListener { 6 | fun onChange(cropRect: RectF) 7 | } 8 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/cropgifticon/view/OnCropImageListener.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.cropgifticon.view 2 | 3 | import android.graphics.Bitmap 4 | import android.graphics.RectF 5 | 6 | interface OnCropImageListener { 7 | fun onCrop(croppedBitmap: Bitmap?, croppedRect: RectF?) 8 | } 9 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/cropgifticon/view/OnCropImagePenListener.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.cropgifticon.view 2 | 3 | import android.graphics.RectF 4 | 5 | interface OnCropImagePenListener { 6 | 7 | fun onPenTouchComplete(drawRect: RectF) 8 | } 9 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/cropgifticon/view/OnCropImageWindowListener.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.cropgifticon.view 2 | 3 | import android.graphics.RectF 4 | 5 | interface OnCropImageWindowListener { 6 | 7 | fun onWindowMove(unconsumedX: Float, unconsumedY: Float, boundRect: RectF) 8 | 9 | fun onWindowResized() 10 | 11 | fun onWindowTouchComplete(curCropRect: RectF) 12 | } 13 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/detailgifticon/GifticonDetailEvent.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.detailgifticon 2 | 3 | sealed class GifticonDetailEvent { 4 | object ScrollDownForUseButtonClicked : GifticonDetailEvent() 5 | object ShareButtonClicked : GifticonDetailEvent() 6 | object ShowAllUsedInfoButtonClicked : GifticonDetailEvent() 7 | data class ShowOriginalImage(val origin: String) : GifticonDetailEvent() 8 | data class ShowLargeBarcode(val barcode: String) : GifticonDetailEvent() 9 | object EditButtonClicked : GifticonDetailEvent() 10 | object UseGifticonButtonClicked : GifticonDetailEvent() 11 | object UseGifticonComplete : GifticonDetailEvent() 12 | object InvalidCashCardUsage : GifticonDetailEvent() 13 | } 14 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/detailgifticon/GifticonDetailMode.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.detailgifticon 2 | 3 | enum class GifticonDetailMode { 4 | UNUSED, USED 5 | } 6 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/edit/addgifticon/adapter/AddCandidateGifticonDisplayModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.edit.addgifticon.adapter 2 | 3 | class AddCandidateGifticonDisplayModel( 4 | var item: AddGifticonItemUIModel.Gifticon, 5 | private val onClick: (AddGifticonItemUIModel.Gifticon) -> Unit, 6 | private val onDelete: (AddGifticonItemUIModel.Gifticon) -> Unit 7 | ) { 8 | 9 | val deleteVisible 10 | get() = item.isDelete 11 | 12 | val invalidVisible 13 | get() = item.isDelete.not() && item.isValid.not() 14 | 15 | fun onClickItem() { 16 | if (item.isDelete) { 17 | onDelete(item) 18 | } else { 19 | onClick(item) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/edit/addgifticon/adapter/AddGifticonItemUIModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.edit.addgifticon.adapter 2 | 3 | import android.net.Uri 4 | import com.lighthouse.presentation.model.CroppedImage 5 | 6 | sealed class AddGifticonItemUIModel { 7 | object Gallery : AddGifticonItemUIModel() 8 | data class Gifticon( 9 | val id: Long, 10 | val origin: Uri, 11 | val thumbnailImage: CroppedImage, 12 | val isSelected: Boolean, 13 | val isDelete: Boolean, 14 | val isValid: Boolean 15 | ) : AddGifticonItemUIModel() { 16 | 17 | val uri: Uri 18 | get() = thumbnailImage.uri ?: origin 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/edit/addgifticon/adapter/AddGotoGalleryViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.edit.addgifticon.adapter 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.lighthouse.presentation.R 7 | import com.lighthouse.presentation.databinding.ItemAddGotoGalleryBinding 8 | 9 | class AddGotoGalleryViewHolder( 10 | parent: ViewGroup, 11 | onClick: () -> Unit, 12 | binding: ItemAddGotoGalleryBinding = ItemAddGotoGalleryBinding.bind( 13 | LayoutInflater.from(parent.context).inflate(R.layout.item_add_goto_gallery, parent, false) 14 | ) 15 | ) : RecyclerView.ViewHolder(binding.root) { 16 | 17 | init { 18 | binding.viewGotoGalleryRippleEffect.setOnClickListener { 19 | onClick() 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/edit/addgifticon/event/AddGifticonCrop.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.edit.addgifticon.event 2 | 3 | enum class AddGifticonCrop { 4 | GIFTICON_IMAGE, 5 | GIFTICON_NAME, 6 | BRAND_NAME, 7 | BARCODE, 8 | BALANCE, 9 | EXPIRED 10 | } 11 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/edit/addgifticon/event/AddGifticonTag.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.edit.addgifticon.event 2 | 3 | enum class AddGifticonTag(val needKeyboard: Boolean) { 4 | GIFTICON_NAME(true), 5 | BRAND_NAME(true), 6 | APPROVE_BRAND_NAME(false), 7 | BARCODE(true), 8 | BALANCE(true), 9 | APPROVE_GIFTICON_IMAGE(false), 10 | NONE(false) 11 | } 12 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/edit/modifygifticon/event/ModifyGifticonCrop.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.edit.modifygifticon.event 2 | 3 | enum class ModifyGifticonCrop { 4 | GIFTICON_IMAGE, 5 | GIFTICON_NAME, 6 | BRAND_NAME, 7 | BARCODE, 8 | BALANCE, 9 | EXPIRED 10 | } 11 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/edit/modifygifticon/event/ModifyGifticonTag.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.edit.modifygifticon.event 2 | 3 | enum class ModifyGifticonTag(val needKeyboard: Boolean) { 4 | GIFTICON_NAME(true), 5 | BRAND_NAME(true), 6 | APPROVE_BRAND_NAME(false), 7 | BARCODE(true), 8 | BALANCE(true), 9 | NONE(false) 10 | } 11 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/gallery/adapter/GallerySelection.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.gallery.adapter 2 | 3 | import com.lighthouse.presentation.model.GalleryUIModel 4 | 5 | class GallerySelection( 6 | private var selected: List = listOf() 7 | ) { 8 | val size 9 | get() = selected.size 10 | 11 | fun toArrayList(): ArrayList = ArrayList(selected) 12 | 13 | fun isSelected(model: GalleryUIModel.Gallery): Boolean { 14 | return model in selected 15 | } 16 | 17 | fun toggle(model: GalleryUIModel.Gallery) { 18 | selected = if (model in selected) { 19 | selected.filter { 20 | it != model 21 | } 22 | } else { 23 | selected + listOf(model) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/gallery/adapter/list/GalleryDisplayModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.gallery.adapter.list 2 | 3 | import com.lighthouse.presentation.model.GalleryUIModel 4 | import com.lighthouse.presentation.util.resource.UIText 5 | 6 | class GalleryDisplayModel( 7 | var item: GalleryUIModel.Gallery, 8 | private val onClick: (GalleryUIModel.Gallery) -> Unit 9 | ) { 10 | val isSelected 11 | get() = item.selectedOrder != -1 12 | 13 | val selectedOrder 14 | get() = if (isSelected) { 15 | UIText.DynamicString("${item.selectedOrder + 1}") 16 | } else { 17 | UIText.Empty 18 | } 19 | 20 | fun onClickItem() { 21 | onClick(item) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/gallery/adapter/list/GalleryHeaderViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.gallery.adapter.list 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.lighthouse.presentation.R 7 | import com.lighthouse.presentation.databinding.ItemGalleryHeaderBinding 8 | import com.lighthouse.presentation.model.GalleryUIModel 9 | 10 | class GalleryHeaderViewHolder( 11 | parent: ViewGroup, 12 | private val binding: ItemGalleryHeaderBinding = ItemGalleryHeaderBinding.bind( 13 | LayoutInflater.from(parent.context).inflate(R.layout.item_gallery_header, parent, false) 14 | ) 15 | ) : RecyclerView.ViewHolder(binding.root) { 16 | 17 | fun bind(item: GalleryUIModel.Header) { 18 | binding.item = item 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/gallery/adapter/selected/SelectedGalleryDisplayModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.gallery.adapter.selected 2 | 3 | import com.lighthouse.presentation.model.GalleryUIModel 4 | 5 | class SelectedGalleryDisplayModel( 6 | val item: GalleryUIModel.Gallery, 7 | private val onClick: (GalleryUIModel.Gallery) -> Unit 8 | ) { 9 | fun onClickItem() { 10 | onClick(item) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/gallery/adapter/selected/SelectedGalleryItemViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.gallery.adapter.selected 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.lighthouse.presentation.R 7 | import com.lighthouse.presentation.databinding.ItemSelectedGalleryBinding 8 | import com.lighthouse.presentation.model.GalleryUIModel 9 | 10 | class SelectedGalleryItemViewHolder( 11 | parent: ViewGroup, 12 | private val onClick: (GalleryUIModel.Gallery) -> Unit, 13 | private val binding: ItemSelectedGalleryBinding = ItemSelectedGalleryBinding.bind( 14 | LayoutInflater.from(parent.context).inflate(R.layout.item_selected_gallery, parent, false) 15 | ) 16 | ) : RecyclerView.ViewHolder(binding.root) { 17 | 18 | fun bind(item: GalleryUIModel.Gallery) { 19 | binding.dm = SelectedGalleryDisplayModel(item, onClick) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/gallery/event/GalleryEvent.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.gallery.event 2 | 3 | sealed class GalleryEvent { 4 | 5 | object PopupBackStack : GalleryEvent() 6 | 7 | object CompleteSelect : GalleryEvent() 8 | } 9 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/gifticonlist/GifticonListViewState.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.gifticonlist 2 | 3 | import com.lighthouse.domain.model.Brand 4 | import com.lighthouse.presentation.model.GifticonSortBy 5 | import com.lighthouse.presentation.model.GifticonUIModel 6 | 7 | data class GifticonListViewState( 8 | val sortBy: GifticonSortBy = GifticonSortBy.DEADLINE, 9 | val gifticons: List = emptyList(), 10 | val loading: Boolean = false, 11 | val brands: List = emptyList(), 12 | val selectedFilter: Set = emptySet(), 13 | val entireBrandsDialogShown: Boolean = false, 14 | val errorMessage: String? = null, 15 | ) 16 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/history/adapter/gifticondetail/HistoryHeaderViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.history.adapter.gifticondetail 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.lighthouse.presentation.R 7 | import com.lighthouse.presentation.databinding.ItemHistoryHeaderBinding 8 | import com.lighthouse.presentation.model.HistoryUiModel 9 | 10 | class HistoryHeaderViewHolder( 11 | parent: ViewGroup, 12 | private val binding: ItemHistoryHeaderBinding = ItemHistoryHeaderBinding.bind( 13 | LayoutInflater.from(parent.context).inflate(R.layout.item_history_header, parent, false), 14 | ), 15 | ) : RecyclerView.ViewHolder(binding.root) { 16 | 17 | fun bind(item: HistoryUiModel.Header) { 18 | binding.item = item 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/home/HomeEmptyFragment.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.home 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import androidx.fragment.app.Fragment 6 | import androidx.fragment.app.activityViewModels 7 | import com.lighthouse.presentation.R 8 | import com.lighthouse.presentation.databinding.FragmentHomeEmptyBinding 9 | import com.lighthouse.presentation.ui.common.viewBindings 10 | import com.lighthouse.presentation.ui.main.MainViewModel 11 | import dagger.hilt.android.AndroidEntryPoint 12 | 13 | @AndroidEntryPoint 14 | class HomeEmptyFragment : Fragment(R.layout.fragment_home_empty) { 15 | 16 | private val binding: FragmentHomeEmptyBinding by viewBindings() 17 | private val mainViewModel: MainViewModel by activityViewModels() 18 | 19 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 20 | super.onViewCreated(view, savedInstanceState) 21 | binding.lifecycleOwner = viewLifecycleOwner 22 | binding.vm = mainViewModel 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/home/HomeEvent.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.home 2 | 3 | import com.lighthouse.presentation.model.BrandPlaceInfoUiModel 4 | import com.lighthouse.presentation.model.GifticonUIModel 5 | 6 | sealed class HomeEvent { 7 | 8 | data class NavigateMap(val gifticons: List, val nearBrandsInfo: List) : HomeEvent() 9 | object RequestLocationPermissionCheck : HomeEvent() 10 | } 11 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/home/adapter/NearGifticonDisplayModel.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.home.adapter 2 | 3 | import com.lighthouse.presentation.R 4 | import com.lighthouse.presentation.model.GifticonWithDistanceUIModel 5 | import com.lighthouse.presentation.util.resource.UIText 6 | 7 | class NearGifticonDisplayModel( 8 | val item: GifticonWithDistanceUIModel 9 | ) { 10 | fun distance(): UIText { 11 | val meter = calculate(item.distance) 12 | return when (meter > MINIMUM_MITER) { 13 | true -> UIText.StringResource(R.string.home_near_gifticon_distance, meter) 14 | false -> UIText.StringResource(R.string.home_near_gifticon_announce) 15 | } 16 | } 17 | 18 | private fun calculate(distance: Int): Int { 19 | val div = distance / MINIMUM_CRITERIA_MITER 20 | return div * MINIMUM_CRITERIA_MITER 21 | } 22 | 23 | companion object { 24 | private const val MINIMUM_CRITERIA_MITER = 10 25 | private const val MINIMUM_MITER = 100 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/main/MainEvent.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.main 2 | 3 | sealed class MainEvent { 4 | 5 | object NavigateAddGifticon : MainEvent() 6 | data class NavigateMap(val brand: String) : MainEvent() 7 | } 8 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/main/MainPage.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.main 2 | 3 | enum class MainPage { 4 | LIST, HOME, SETTING, OTHER 5 | } 6 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/map/MapEvent.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.map 2 | 3 | sealed class MapEvent { 4 | 5 | object NavigateHome : MapEvent() 6 | data class DeleteMarker(val marker: List) : MapEvent() 7 | } 8 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/map/OnLocationUpdateListener.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.map 2 | 3 | import android.location.Location 4 | 5 | interface OnLocationUpdateListener { 6 | fun onLocationUpdated(location: Location) 7 | } 8 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/security/AuthCallback.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.security 2 | 3 | import androidx.annotation.StringRes 4 | 5 | interface AuthCallback { 6 | fun onAuthSuccess() 7 | fun onAuthCancel() 8 | fun onAuthError(@StringRes stringId: Int? = null) 9 | } 10 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/security/event/SecurityDirections.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.security.event 2 | 3 | enum class SecurityDirections { 4 | PIN, 5 | FINGERPRINT, 6 | LOCATION, 7 | MAIN 8 | } 9 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/security/pin/PinSettingType.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.security.pin 2 | 3 | enum class PinSettingType { 4 | INITIAL, 5 | CONFIRM, 6 | WRONG, 7 | COMPLETE, 8 | ERROR, 9 | WAIT 10 | } 11 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/setting/SecurityOption.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.setting 2 | 3 | enum class SecurityOption(val text: String) { 4 | NONE("사용 안 함"), 5 | PIN("PIN"), 6 | FINGERPRINT("지문") 7 | } 8 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/setting/UserPreferenceState.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.setting 2 | 3 | data class UserPreferenceState( 4 | val guest: Boolean = true, 5 | val security: SecurityOption = SecurityOption.NONE, 6 | val notification: Boolean = true 7 | ) 8 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/widget/BeepWidgetReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.widget 2 | 3 | import android.content.Context 4 | import androidx.glance.appwidget.GlanceAppWidget 5 | import androidx.glance.appwidget.GlanceAppWidgetReceiver 6 | import com.lighthouse.presentation.background.BeepWorkManager 7 | 8 | class BeepWidgetReceiver : GlanceAppWidgetReceiver() { 9 | 10 | override val glanceAppWidget: GlanceAppWidget 11 | get() = BeepWidget() 12 | 13 | override fun onEnabled(context: Context) { 14 | super.onEnabled(context) 15 | BeepWorkManager.getInstance(context).widgetEnqueue() 16 | } 17 | 18 | /** 19 | * 이 친구는 모든 위젯이 없어졌을때 실행될 얘입니다. 20 | */ 21 | override fun onDisabled(context: Context) { 22 | super.onDisabled(context) 23 | BeepWorkManager.getInstance(context).widgetCancel() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/ui/widget/WidgetState.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.ui.widget 2 | 3 | import kotlinx.serialization.Serializable 4 | 5 | @Serializable 6 | sealed interface WidgetState { 7 | 8 | @Serializable 9 | object Loading : WidgetState 10 | 11 | @Serializable 12 | object Empty : WidgetState 13 | 14 | @Serializable 15 | object NoExistsLocationPermission : WidgetState 16 | 17 | @Serializable 18 | data class Available(val gifticons: List, Int?>>) : WidgetState 19 | 20 | @Serializable 21 | data class Unavailable(val message: String) : WidgetState 22 | } 23 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/OnThrottleClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util 2 | 3 | import android.view.View 4 | import android.view.View.OnClickListener 5 | 6 | abstract class OnThrottleClickListener : OnClickListener { 7 | 8 | private var recentClickTime: Long = 0L 9 | 10 | private val isSafe: Boolean 11 | get() = System.currentTimeMillis() - recentClickTime > THROTTLE_TIME 12 | 13 | override fun onClick(view: View) { 14 | if (isSafe) { 15 | recentClickTime = System.currentTimeMillis() 16 | onThrottleClick(view) 17 | } 18 | } 19 | 20 | abstract fun onThrottleClick(view: View) 21 | 22 | companion object { 23 | private const val THROTTLE_TIME = 500L 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/UUID.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util 2 | 3 | import java.util.UUID 4 | 5 | object UUID { 6 | fun generate() = UUID.randomUUID().toString() 7 | } 8 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/flow/Combine.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.flow 2 | 3 | import kotlinx.coroutines.flow.Flow 4 | import kotlinx.coroutines.flow.combine 5 | 6 | /** 7 | * 6 개의 플로우를 combine 8 | */ 9 | fun combine( 10 | flow: Flow, 11 | flow2: Flow, 12 | flow3: Flow, 13 | flow4: Flow, 14 | flow5: Flow, 15 | flow6: Flow, 16 | transform: suspend (T1, T2, T3, T4, T5, T6) -> R 17 | ): Flow = combine( 18 | combine(flow, flow2, flow3, ::Triple), 19 | combine(flow4, flow5, flow6, ::Triple) 20 | ) { t1, t2 -> 21 | transform( 22 | t1.first, 23 | t1.second, 24 | t1.third, 25 | t2.first, 26 | t2.second, 27 | t2.third 28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/parser/CConParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.parser 2 | 3 | class CConParser(input: List) : BaseParser(input) { 4 | override val keywords = listOf("ccon", "c콘") 5 | 6 | override val exactExcludes = listOf("înumber", "inumber", "상품명", "교환처", "유효기간", "쿠폰번호") 7 | 8 | override val containExcludes = listOf() 9 | 10 | private val titleRegex = "상품명\\s+(.*)".toRegex() 11 | private val brandRegex = "교환처\\s+(.*)".toRegex() 12 | 13 | override val title = info.mapNotNull { str -> 14 | titleRegex.find(str)?.groups?.get(1)?.value?.trim() 15 | }.getOrNull(0) ?: "" 16 | 17 | override val brand = info.mapNotNull { str -> 18 | brandRegex.find(str)?.groups?.get(1)?.value?.trim() 19 | }.getOrNull(0) ?: "" 20 | 21 | override val candidateList = super.candidateList.map { str -> 22 | titleRegex.find(str)?.groups?.get(1)?.value?.trim() ?: brandRegex.find(str)?.groups?.get(1)?.value?.trim() 23 | ?: str 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/parser/DefaultParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.parser 2 | 3 | class DefaultParser(input: List) : BaseParser(input) { 4 | override val keywords = listOf("gifticon") 5 | 6 | override val match by lazy { 7 | false 8 | } 9 | 10 | override val title by lazy { 11 | candidateList.getOrElse(0) { "" } 12 | } 13 | 14 | override val brand by lazy { 15 | candidateList.getOrElse(1) { "" } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/parser/GifticonParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.parser 2 | 3 | object GifticonParser { 4 | fun parse(input: List): BaseParser { 5 | val kakaoParser = KakaoParser(input) 6 | if (kakaoParser.match) { 7 | return kakaoParser 8 | } 9 | val syrupParser = SyrupParser(input) 10 | if (syrupParser.match) { 11 | return syrupParser 12 | } 13 | val cConParser = CConParser(input) 14 | if (cConParser.match) { 15 | return cConParser 16 | } 17 | val giftishowParser = GiftishowParser(input) 18 | if (giftishowParser.match) { 19 | return giftishowParser 20 | } 21 | return DefaultParser(input) 22 | } 23 | 24 | fun parse(input: String): BaseParser { 25 | return parse(input.split(input, "\n")) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/parser/KakaoParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.parser 2 | 3 | class KakaoParser(input: List) : BaseParser(input) { 4 | override val keywords = listOf("kakaotalk") 5 | 6 | override val exactExcludes = listOf("교환처", "유효기간", "주문번호") 7 | 8 | override val containExcludes = listOf() 9 | } 10 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/parser/SyrupParser.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.parser 2 | 3 | class SyrupParser(input: List) : BaseParser(input) { 4 | override val keywords = listOf("gifticon", "syrup") 5 | 6 | override val exactExcludes = listOf("사용기한", "사용처") 7 | 8 | override val containExcludes = listOf("교환수량", "기프티콘") 9 | 10 | override val match by lazy { 11 | input.any { str -> 12 | str.lowercase().trim().contains("syrup") 13 | } || input.count { str -> str.lowercase().trim().contains("gifticon") } == 2 14 | } 15 | 16 | private val brandRegex = "사용처\\s(.*)".toRegex() 17 | 18 | override val brand = info.mapNotNull { 19 | brandRegex.find(it)?.groups?.get(1)?.value?.trim() 20 | }.getOrNull(0) ?: "" 21 | 22 | override val candidateList = super.candidateList.map { str -> 23 | brandRegex.find(str)?.groups?.get(1)?.value?.trim() ?: str 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/permission/LocationPermissionManager.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.permission 2 | 3 | import android.Manifest 4 | import android.app.Activity 5 | import android.os.Build 6 | import com.lighthouse.presentation.util.permission.core.PermissionManager 7 | 8 | class LocationPermissionManager(activity: Activity) : PermissionManager(activity) { 9 | 10 | override val additionalPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 11 | arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION) 12 | } else { 13 | emptyArray() 14 | } 15 | 16 | override val permissions = 17 | arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION) 18 | } 19 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/permission/StoragePermissionManager.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.permission 2 | 3 | import android.Manifest 4 | import android.app.Activity 5 | import android.os.Build 6 | import com.lighthouse.presentation.util.permission.core.PermissionManager 7 | 8 | class StoragePermissionManager(activity: Activity) : PermissionManager(activity) { 9 | 10 | override val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { 11 | arrayOf(Manifest.permission.READ_MEDIA_IMAGES) 12 | } else { 13 | arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/permission/core/ActivityPermissionDelegate.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.permission.core 2 | 3 | import android.app.Activity 4 | import androidx.core.app.ComponentActivity 5 | import androidx.lifecycle.LifecycleOwner 6 | import kotlin.reflect.KProperty 7 | 8 | class ActivityPermissionDelegate( 9 | lifecycleOwner: LifecycleOwner, 10 | private val activity: Activity, 11 | private val managerClass: Class 12 | ) : PermissionDelegate(lifecycleOwner) { 13 | 14 | override fun getValue(thisRef: LifecycleOwner, property: KProperty<*>): PM { 15 | manager?.let { 16 | return it 17 | } 18 | 19 | return PermissionFactory().create(activity, managerClass).also { 20 | manager = it 21 | } 22 | } 23 | } 24 | 25 | inline fun ComponentActivity.permissions() = 26 | ActivityPermissionDelegate(this, this, PM::class.java) 27 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/permission/core/BeepPermissionState.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.permission.core 2 | 3 | sealed class BeepPermissionState { 4 | object NotAllowedPermission : BeepPermissionState() 5 | object AllAllowedPermission : BeepPermissionState() 6 | object PartiallyAllowedPermission : BeepPermissionState() 7 | } 8 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/permission/core/FragmentPermissionDelegate.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.permission.core 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.lifecycle.LifecycleOwner 5 | import kotlin.reflect.KProperty 6 | 7 | class FragmentPermissionDelegate( 8 | lifecycleOwner: LifecycleOwner, 9 | private val fragment: Fragment, 10 | private val managerClass: Class 11 | ) : PermissionDelegate(lifecycleOwner) { 12 | 13 | override fun getValue(thisRef: LifecycleOwner, property: KProperty<*>): PM { 14 | manager?.let { 15 | return it 16 | } 17 | 18 | return PermissionFactory().create(fragment.requireActivity(), managerClass).also { 19 | manager = it 20 | } 21 | } 22 | } 23 | 24 | inline fun Fragment.permissions() = 25 | FragmentPermissionDelegate(this, this, PM::class.java) 26 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/permission/core/PermissionDelegate.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.permission.core 2 | 3 | import androidx.lifecycle.DefaultLifecycleObserver 4 | import androidx.lifecycle.LifecycleOwner 5 | import kotlin.properties.ReadOnlyProperty 6 | 7 | abstract class PermissionDelegate( 8 | lifecycleOwner: LifecycleOwner 9 | ) : ReadOnlyProperty { 10 | 11 | protected var manager: PM? = null 12 | 13 | init { 14 | lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver { 15 | override fun onStart(owner: LifecycleOwner) { 16 | val manager = manager 17 | if (manager != null) { 18 | manager.permissionFlow.value = manager.isGrant 19 | } 20 | } 21 | 22 | override fun onDestroy(owner: LifecycleOwner) { 23 | lifecycleOwner.lifecycle.removeObserver(this) 24 | } 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/permission/core/PermissionFactory.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.permission.core 2 | 3 | import android.app.Activity 4 | import com.lighthouse.presentation.util.permission.LocationPermissionManager 5 | import com.lighthouse.presentation.util.permission.StoragePermissionManager 6 | 7 | class PermissionFactory { 8 | fun create(activity: Activity, managerClass: Class): PM { 9 | return when (managerClass) { 10 | StoragePermissionManager::class.java -> StoragePermissionManager(activity) 11 | LocationPermissionManager::class.java -> LocationPermissionManager(activity) 12 | else -> throw IllegalArgumentException("존재하지 않는 Permission Manager입니다.") 13 | } as PM 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /presentation/src/main/java/com/lighthouse/presentation/util/resource/AnimInfo.kt: -------------------------------------------------------------------------------- 1 | package com.lighthouse.presentation.util.resource 2 | 3 | import android.view.animation.Animation 4 | import androidx.annotation.AnimRes 5 | 6 | sealed class AnimInfo { 7 | 8 | object Empty : AnimInfo() 9 | 10 | data class DynamicAnim(val animation: Animation, val condition: Boolean) : AnimInfo() 11 | 12 | data class AnimResource( 13 | @AnimRes val resId: Int, 14 | val condition: Boolean 15 | ) : AnimInfo() 16 | } 17 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_bounce.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 16 | 17 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_fadein_up.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 16 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_jump.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_shake.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_slide_in_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_slide_in_left.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_slide_in_right.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_slide_out_left.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_slide_out_right.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_slide_out_top.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/anim/anim_stamp.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/black_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/black_36.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/black_50.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/black_60.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/on_primary_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/on_surface_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/on_surface_50.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/on_surface_60.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/on_surface_87.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/on_surface_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/color/primary.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable-night/ic_widget_accommodation.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable-night/ic_widget_culture.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 16 | 17 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable-nodpi/widget_gifticon_preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/drawable-nodpi/widget_gifticon_preview.jpg -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_black_50.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_bottom_sheet_handle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_circle_black_50.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_corner_top_20.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_gallery.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_gallery_selected.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_gifticon_memo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_history_cancel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_history_init.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_history_modify.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_history_use.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_map_bottom_sheet_24.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_on_surface_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_on_surface_50.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_origin_gifticon.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_primary_corner_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_stroke_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bg_widget_small_6.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/bottom_sheet_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/btn_main_floating_add.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_add_goto_gallery.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_add_warning_badge.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_arrow_forward.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_back.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_check.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_confirm.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_crop.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_double_arrow_down.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_edit_gifticon_calendar.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_history.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_item_invalid.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 8 | 9 | 10 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_location.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_main_menu_home.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_main_menu_list.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_marker_accommodation.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 19 | 20 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_marker_base.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_marker_culture.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 19 | 20 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_mode_edit.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_origin_gifticon.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_outline_info.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_pin_backspace.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_pin_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 10 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_pin_filled.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_question.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_remove.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_share.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_splash_beep.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_warning.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_widget_accommodation.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_widget_culture.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 16 | 17 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ic_widget_refresh_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/img_item_delete.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/img_item_invalid.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/img_stamp.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ripple_add_gifticon_candidate.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ripple_circle_on_primary_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ripple_circle_on_surface_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ripple_primary_corner_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ripple_rect_corner_8_on_primary_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/ripple_rect_corner_8_on_surface_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/tc_on_primary_disabled.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/drawable/tc_on_primary_disabled_night.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/layout/activity_security.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /presentation/src/main/res/layout/activity_sign_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /presentation/src/main/res/layout/dialog_origin_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 17 | 18 | -------------------------------------------------------------------------------- /presentation/src/main/res/layout/dialog_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /presentation/src/main/res/layout/fragment_gifticon_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /presentation/src/main/res/layout/fragment_home_container.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /presentation/src/main/res/layout/widget_loading_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /presentation/src/main/res/menu/menu_gifticon_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | -------------------------------------------------------------------------------- /presentation/src/main/res/menu/menu_main_navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 12 | 13 | 17 | -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /presentation/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boostcampwm-2022/android04-BEEP/481acc949bbfbdcfcaaed73630ea95caf6c55112/presentation/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /presentation/src/main/res/navigation/nav_graph.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /presentation/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #000000 4 | 5 | #B0777777 6 | #B0FF0000 7 | #B00000FF 8 | #B006DA79 9 | -------------------------------------------------------------------------------- /presentation/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /presentation/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 300dp 4 | 65dp 5 | -------------------------------------------------------------------------------- /presentation/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /presentation/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 15 | -------------------------------------------------------------------------------- /presentation/src/main/res/xml/gifticon_widget_provider.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | @file:Suppress("UnstableApiUsage") 2 | 3 | pluginManagement { 4 | includeBuild("build-logic") 5 | repositories { 6 | google() 7 | mavenCentral() 8 | gradlePluginPortal() 9 | } 10 | } 11 | 12 | dependencyResolutionManagement { 13 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 14 | repositories { 15 | google() 16 | mavenCentral() 17 | maven("https://naver.jfrog.io/artifactory/maven/") 18 | } 19 | } 20 | rootProject.name = "BEEP" 21 | 22 | fun includeProject(moduleName: String, rootFolderName: String = "") { 23 | settings.include(moduleName) 24 | 25 | if (rootFolderName.isNotEmpty()) { 26 | project(moduleName).projectDir = 27 | File(rootDir, "$rootFolderName/${moduleName.substring(startIndex = 1)}") 28 | } 29 | } 30 | 31 | includeProject(":app") 32 | includeProject(":data") 33 | includeProject(":presentation") 34 | includeProject(":domain") 35 | --------------------------------------------------------------------------------