├── .circleci └── config.yml ├── .gitignore ├── AMAZON1.png ├── APPSTORE1.png ├── BUILD.md ├── CANARY.asc ├── CONTRIBUTING.md ├── DASHBOARDLOGOS.png ├── FDROID1.png ├── GOOGLEPLAY1.png ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── config │ ├── detekt-config.yml │ ├── jacoco.gradle │ └── sonarqube.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── org │ │ └── secfirst │ │ └── umbrella │ │ └── whitelabel │ │ ├── ExampleInstrumentedTest.kt │ │ ├── HostFormControllerTest.kt │ │ └── misc │ │ ├── CustomAssertions.kt │ │ └── CustomMatchers.kt │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── default_rss.json │ │ ├── fonts │ │ │ ├── Roboto-Medium.ttf │ │ │ └── Roboto-Regular.ttf │ │ └── terms.html │ ├── java │ │ └── org │ │ │ └── secfirst │ │ │ └── umbrella │ │ │ ├── UmbrellaApplication.kt │ │ │ ├── component │ │ │ ├── AutoFitGridLayoutManager.kt │ │ │ ├── ColumnGroup.kt │ │ │ ├── DialogManager.kt │ │ │ ├── InfiniteScrollListener.kt │ │ │ ├── ItemDecoration.kt │ │ │ ├── RefreshIntervalDialog.kt │ │ │ ├── SwipeToDeleteCallback.kt │ │ │ └── WebViewController.kt │ │ │ ├── data │ │ │ ├── VirtualStorage.kt │ │ │ ├── database │ │ │ │ ├── AppDatabase.kt │ │ │ │ ├── BaseDao.kt │ │ │ │ ├── SQLCipherHelperImpl.kt │ │ │ │ ├── account │ │ │ │ │ ├── AccountDao.kt │ │ │ │ │ ├── AccountRepo.kt │ │ │ │ │ └── AccountRepository.kt │ │ │ │ ├── checklist │ │ │ │ │ ├── ChecklistDao.kt │ │ │ │ │ ├── ChecklistRepo.kt │ │ │ │ │ ├── ChecklistRepository.kt │ │ │ │ │ └── entity.kt │ │ │ │ ├── content │ │ │ │ │ ├── ContentDao.kt │ │ │ │ │ ├── ContentRepo.kt │ │ │ │ │ ├── ContentRepository.kt │ │ │ │ │ └── entity.kt │ │ │ │ ├── difficulty │ │ │ │ │ ├── DifficultyDao.kt │ │ │ │ │ ├── DifficultyRepo.kt │ │ │ │ │ ├── DifficultyRepository.kt │ │ │ │ │ └── entity.kt │ │ │ │ ├── form │ │ │ │ │ ├── FormDao.kt │ │ │ │ │ ├── FormRepo.kt │ │ │ │ │ ├── FormRepository.kt │ │ │ │ │ └── entity.kt │ │ │ │ ├── lesson │ │ │ │ │ ├── LessonDao.kt │ │ │ │ │ ├── LessonRepo.kt │ │ │ │ │ ├── LessonRepository.kt │ │ │ │ │ └── entity.kt │ │ │ │ ├── login │ │ │ │ │ ├── LoginDao.kt │ │ │ │ │ ├── LoginRepo.kt │ │ │ │ │ └── LoginRepository.kt │ │ │ │ ├── reader │ │ │ │ │ ├── ReaderDao.kt │ │ │ │ │ ├── ReaderRepo.kt │ │ │ │ │ ├── ReaderRepository.kt │ │ │ │ │ └── entity.kt │ │ │ │ └── segment │ │ │ │ │ ├── SegmentDao.kt │ │ │ │ │ ├── SegmentRepo.kt │ │ │ │ │ ├── SegmentRepository.kt │ │ │ │ │ └── entity.kt │ │ │ ├── disk │ │ │ │ ├── TentDao.kt │ │ │ │ ├── TentLoader.kt │ │ │ │ ├── TentMonitor.kt │ │ │ │ ├── TentRepo.kt │ │ │ │ ├── TentRepository.kt │ │ │ │ ├── entity.kt │ │ │ │ └── tent_config.kt │ │ │ ├── network │ │ │ │ ├── NetworkDataObj.kt │ │ │ │ ├── NetworkEndPoint.kt │ │ │ │ ├── NetworkHelper.kt │ │ │ │ └── NetworkReponse.kt │ │ │ └── preferences │ │ │ │ └── AppPreferenceHelper.kt │ │ │ ├── di │ │ │ ├── ApiKeyInfo.kt │ │ │ ├── PreferenceInfo.kt │ │ │ ├── builder │ │ │ │ └── ActivityBuilder.kt │ │ │ ├── component │ │ │ │ └── AppComponent.kt │ │ │ └── module │ │ │ │ └── AppModule.kt │ │ │ ├── feature │ │ │ ├── account │ │ │ │ ├── AccountModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── AccountBaseInteractor.kt │ │ │ │ │ └── AccountInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── AccountBasePresenter.kt │ │ │ │ │ └── AccountPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── AccountController.kt │ │ │ │ │ ├── AccountView.kt │ │ │ │ │ └── SettingsController.kt │ │ │ ├── base │ │ │ │ ├── interactor │ │ │ │ │ ├── BaseInteractor.kt │ │ │ │ │ └── BaseInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── BasePresenter.kt │ │ │ │ │ └── BasePresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── BaseController.kt │ │ │ │ │ └── BaseView.kt │ │ │ ├── checklist │ │ │ │ ├── ChecklistModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── ChecklistBaseInteractor.kt │ │ │ │ │ └── ChecklistInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── ChecklistBasePresenter.kt │ │ │ │ │ └── ChecklistPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── ChecklistView.kt │ │ │ │ │ ├── adapter │ │ │ │ │ ├── ChecklistAdapter.kt │ │ │ │ │ ├── ChecklistCustomAdapter.kt │ │ │ │ │ ├── DashboardAdapter.kt │ │ │ │ │ ├── HostChecklistAdapter.kt │ │ │ │ │ └── PathwaysAdapter.kt │ │ │ │ │ └── controller │ │ │ │ │ ├── ChecklistController.kt │ │ │ │ │ ├── ChecklistCustomController.kt │ │ │ │ │ ├── DashboardController.kt │ │ │ │ │ └── HostChecklistController.kt │ │ │ ├── content │ │ │ │ ├── ContentModule.kt │ │ │ │ ├── ContentService.kt │ │ │ │ ├── ContentView.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── ContentBaseInteractor.kt │ │ │ │ │ └── ContentInteractorImp.kt │ │ │ │ └── presenter │ │ │ │ │ ├── ContentBasePresenter.kt │ │ │ │ │ └── ContentPresenterImp.kt │ │ │ ├── difficulty │ │ │ │ ├── DifficultyModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── DifficultyBaseInteractor.kt │ │ │ │ │ └── DifficultyInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── DifficultyBasePresenter.kt │ │ │ │ │ └── DifficultyPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── DifficultyAdapter.kt │ │ │ │ │ ├── DifficultyController.kt │ │ │ │ │ └── DifficultyView.kt │ │ │ ├── form │ │ │ │ ├── FieldType.kt │ │ │ │ ├── FormModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── FormBaseInteractor.kt │ │ │ │ │ └── FormInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── FormBasePresenter.kt │ │ │ │ │ └── FormPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── FormUI.kt │ │ │ │ │ ├── FormView.kt │ │ │ │ │ ├── adapter │ │ │ │ │ ├── ActiveFormSection.kt │ │ │ │ │ ├── AllFormSection.kt │ │ │ │ │ └── FormAdapter.kt │ │ │ │ │ └── controller │ │ │ │ │ ├── FormController.kt │ │ │ │ │ └── HostFormController.kt │ │ │ ├── lesson │ │ │ │ ├── LessonModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── LessonBaseInteractor.kt │ │ │ │ │ └── LessonInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── LessonBasePresenter.kt │ │ │ │ │ └── LessonPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── LessonController.kt │ │ │ │ │ ├── LessonDecorator.kt │ │ │ │ │ ├── LessonGroup.kt │ │ │ │ │ ├── LessonHeader.kt │ │ │ │ │ ├── LessonItem.kt │ │ │ │ │ └── LessonView.kt │ │ │ ├── login │ │ │ │ ├── LoginModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── LoginBaseInteractor.kt │ │ │ │ │ └── LoginInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── LoginBasePresenter.kt │ │ │ │ │ └── LoginPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── LoginController.kt │ │ │ │ │ └── LoginView.kt │ │ │ ├── main │ │ │ │ └── MainActivity.kt │ │ │ ├── maskapp │ │ │ │ ├── MaskAppModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── MaskAppBaseInteractor.kt │ │ │ │ │ └── MaskAppInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── MaskAppBasePresenter.kt │ │ │ │ │ └── MaskAppPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── CalculatorController.kt │ │ │ │ │ └── MaskAppView.kt │ │ │ ├── reader │ │ │ │ ├── ReaderModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── ReaderBaseInteractor.kt │ │ │ │ │ └── ReaderInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── ReaderBasePresenter.kt │ │ │ │ │ └── ReaderPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── HostReaderController.kt │ │ │ │ │ ├── ReaderAdapter.kt │ │ │ │ │ ├── ReaderView.kt │ │ │ │ │ ├── feed │ │ │ │ │ ├── FeedAdapter.kt │ │ │ │ │ ├── FeedController.kt │ │ │ │ │ ├── FeedEmptyController.kt │ │ │ │ │ ├── FeedLocationDialog.kt │ │ │ │ │ ├── FeedSettingsController.kt │ │ │ │ │ ├── FeedSourceDialog.kt │ │ │ │ │ ├── FeedSourceUI.kt │ │ │ │ │ └── SourcesAdapter.kt │ │ │ │ │ └── rss │ │ │ │ │ ├── ArticleCardAdapter.kt │ │ │ │ │ ├── ArticleController.kt │ │ │ │ │ ├── ArticleSimpleAdapter.kt │ │ │ │ │ ├── RssAdapter.kt │ │ │ │ │ └── RssController.kt │ │ │ ├── search │ │ │ │ ├── SearchModule.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── SearchBaseInteractor.kt │ │ │ │ │ └── SearchInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── SearchBasePresenter.kt │ │ │ │ │ └── SearchPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── DifficultyAdapter.kt │ │ │ │ │ ├── SearchController.kt │ │ │ │ │ └── SearchView.kt │ │ │ ├── segment │ │ │ │ ├── SegmentModule.kt │ │ │ │ ├── SegmentPagination.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── SegmentBaseInteractor.kt │ │ │ │ │ └── SegmentInteractorImp.kt │ │ │ │ ├── presenter │ │ │ │ │ ├── SegmentBasePresenter.kt │ │ │ │ │ └── SegmentPresenterImp.kt │ │ │ │ └── view │ │ │ │ │ ├── SegmentCard.kt │ │ │ │ │ ├── SegmentFoot.kt │ │ │ │ │ ├── SegmentItem.kt │ │ │ │ │ ├── SegmentView.kt │ │ │ │ │ ├── adapter │ │ │ │ │ ├── FilterAdapter.kt │ │ │ │ │ ├── GroupAdapter.kt │ │ │ │ │ └── HostSegmentAdapter.kt │ │ │ │ │ └── controller │ │ │ │ │ ├── HostSegmentController.kt │ │ │ │ │ ├── SegmentController.kt │ │ │ │ │ └── SegmentDetailController.kt │ │ │ ├── tent │ │ │ │ ├── TentModule.kt │ │ │ │ ├── TentView.kt │ │ │ │ ├── interactor │ │ │ │ │ ├── TentBaseInteractor.kt │ │ │ │ │ └── TentInteractorImp.kt │ │ │ │ └── presenter │ │ │ │ │ ├── TentBasePresenter.kt │ │ │ │ │ └── TentPresenterImp.kt │ │ │ └── tour │ │ │ │ ├── TourModule.kt │ │ │ │ └── view │ │ │ │ ├── TourAdapter.kt │ │ │ │ ├── TourController.kt │ │ │ │ └── TourUI.kt │ │ │ └── misc │ │ │ ├── AboutController.kt │ │ │ ├── AppExecutors.kt │ │ │ ├── CoroutineExt.kt │ │ │ ├── CountryHelper.kt │ │ │ ├── Extensions.kt │ │ │ ├── StringEtx.kt │ │ │ ├── ViewExt.kt │ │ │ └── umbrella_uri.kt │ └── res │ │ ├── animator │ │ ├── opacity_pulse.xml │ │ ├── rotation_collapse_to_expand.xml │ │ └── rotation_expand_to_collapse.xml │ │ ├── color │ │ └── nav_item_color_state.xml │ │ ├── drawable-hdpi │ │ ├── ae.png │ │ ├── cn.png │ │ ├── dialog_bg.xml │ │ ├── es.png │ │ ├── fr.png │ │ ├── gb.png │ │ ├── ic_account_box.png │ │ ├── ic_alarm.png │ │ ├── ic_checklist.png │ │ ├── ic_form.png │ │ ├── ic_local_library.png │ │ ├── ic_person_pin_circle.png │ │ ├── ic_shake.png │ │ ├── ic_share_segment.png │ │ ├── ic_star_border.png │ │ ├── ic_star_selected.png │ │ ├── ic_view_feed.png │ │ ├── ic_walkthrough.png │ │ ├── ic_walkthrough1.png │ │ ├── ic_walkthrough2.png │ │ ├── ic_walkthrough3.png │ │ ├── ir.png │ │ ├── login_umbrella.png │ │ ├── popup_fixed_alert.9.png │ │ ├── ru.png │ │ └── ta.png │ │ ├── drawable-mdpi │ │ ├── ae.png │ │ ├── es.png │ │ ├── fr.png │ │ ├── gb.png │ │ ├── ic_star_border.png │ │ ├── ic_star_selected.png │ │ ├── ic_walkthrough1.png │ │ ├── ic_walkthrough2.png │ │ ├── ic_walkthrough3.png │ │ ├── ir.png │ │ ├── ru.png │ │ └── ta.png │ │ ├── drawable-xhdpi │ │ ├── ae.png │ │ ├── baseline_search_white_36.png │ │ ├── cn.png │ │ ├── es.png │ │ ├── fr.png │ │ ├── gb.png │ │ ├── ic_account_box.png │ │ ├── ic_add_white.png │ │ ├── ic_alarm.png │ │ ├── ic_beginner.png │ │ ├── ic_cast_connected.png │ │ ├── ic_checklist.png │ │ ├── ic_delete.png │ │ ├── ic_expert.png │ │ ├── ic_fav.png │ │ ├── ic_fav_selected.png │ │ ├── ic_form.png │ │ ├── ic_intermediate.png │ │ ├── ic_local_library.png │ │ ├── ic_mode_edit.png │ │ ├── ic_person_pin_circle.png │ │ ├── ic_shake.png │ │ ├── ic_share.png │ │ ├── ic_share_segment.png │ │ ├── ic_star_border.png │ │ ├── ic_star_selected.png │ │ ├── ic_view_feed.png │ │ ├── ic_walkthrough.png │ │ ├── ic_walkthrough1.png │ │ ├── ic_walkthrough2.png │ │ ├── ic_walkthrough3.png │ │ ├── ir.png │ │ ├── login_umbrella.png │ │ ├── popup_fixed_alert.9.png │ │ ├── ru.png │ │ └── ta.png │ │ ├── drawable-xxhdpi │ │ ├── ae.png │ │ ├── baseline_search_white_36.png │ │ ├── cn.png │ │ ├── default_image.png │ │ ├── es.png │ │ ├── fr.png │ │ ├── gb.png │ │ ├── ic_account_box.png │ │ ├── ic_add_white.png │ │ ├── ic_alarm.png │ │ ├── ic_beginner.png │ │ ├── ic_cast_connected.png │ │ ├── ic_checklist.png │ │ ├── ic_delete.png │ │ ├── ic_expert.png │ │ ├── ic_fav.png │ │ ├── ic_fav_selected.png │ │ ├── ic_form.png │ │ ├── ic_intermediate.png │ │ ├── ic_keyboard_arrow_down_black.xml │ │ ├── ic_keyboard_arrow_up_black.xml │ │ ├── ic_local_library.png │ │ ├── ic_mode_edit.png │ │ ├── ic_person_pin_circle.png │ │ ├── ic_shake.png │ │ ├── ic_share.png │ │ ├── ic_share_segment.png │ │ ├── ic_star_border.png │ │ ├── ic_star_selected.png │ │ ├── ic_view_feed.png │ │ ├── ic_walkthrough.png │ │ ├── ic_walkthrough1.png │ │ ├── ic_walkthrough2.png │ │ ├── ic_walkthrough3.png │ │ ├── ir.png │ │ ├── login_umbrella.png │ │ ├── ms_right_arrow.xml │ │ ├── popup_fixed_alert.9.png │ │ ├── ru.png │ │ └── ta.png │ │ ├── drawable-xxxhdpi │ │ ├── ae.png │ │ ├── baseline_search_white_36.png │ │ ├── cn.png │ │ ├── es.png │ │ ├── fr.png │ │ ├── gb.png │ │ ├── ic_account_box.png │ │ ├── ic_add_white.png │ │ ├── ic_alarm.png │ │ ├── ic_beginner.png │ │ ├── ic_cast_connected.png │ │ ├── ic_checklist.png │ │ ├── ic_delete.png │ │ ├── ic_expert.png │ │ ├── ic_fav.png │ │ ├── ic_fav_selected.png │ │ ├── ic_form.png │ │ ├── ic_intermediate.png │ │ ├── ic_local_library.png │ │ ├── ic_mode_edit.png │ │ ├── ic_person_pin_circle.png │ │ ├── ic_shake.png │ │ ├── ic_share.png │ │ ├── ic_share_segment.png │ │ ├── ic_star_border.png │ │ ├── ic_star_selected.png │ │ ├── ic_total_done.png │ │ ├── ic_view_feed.png │ │ ├── ic_walkthrough.png │ │ ├── ic_walkthrough1.png │ │ ├── ic_walkthrough2.png │ │ ├── ic_walkthrough3.png │ │ ├── ir.png │ │ ├── login_umbrella.png │ │ ├── ru.png │ │ ├── ta.png │ │ ├── umbrella190.png │ │ ├── walktrough2.png │ │ ├── walktrough3.png │ │ └── walktrough4.png │ │ ├── drawable │ │ ├── baseline_search_24.xml │ │ ├── collapse.xml │ │ ├── collapse_animated.xml │ │ ├── expand.xml │ │ ├── expand_animated.xml │ │ ├── favorite_bg.xml │ │ ├── ic_action_back.xml │ │ ├── ic_dashboard_black_24dp.xml │ │ ├── ic_fav.png │ │ ├── ic_fav_selected.png │ │ ├── ic_home_black_24dp.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_menu_search.png │ │ ├── ic_notifications_black_24dp.xml │ │ └── round_button.xml │ │ ├── layout │ │ ├── about.xml │ │ ├── account_language_dialog.xml │ │ ├── account_password_alert.xml │ │ ├── account_reset_password_alert.xml │ │ ├── account_settings_view.xml │ │ ├── account_skip_alert.xml │ │ ├── account_switch_server_view.xml │ │ ├── account_view.xml │ │ ├── active_form_item_view.xml │ │ ├── add_rss_dialog.xml │ │ ├── alert_control.xml │ │ ├── all_form_item_view.xml │ │ ├── article_view.xml │ │ ├── calculator_view.xml │ │ ├── card_article_view.xml │ │ ├── checklist_action_dialog.xml │ │ ├── checklist_add_item_dialog.xml │ │ ├── checklist_custom_dialog.xml │ │ ├── checklist_custom_item.xml │ │ ├── checklist_custom_view.xml │ │ ├── checklist_dashboard.xml │ │ ├── checklist_dashboard_footer.xml │ │ ├── checklist_dashboard_header.xml │ │ ├── checklist_dashboard_item.xml │ │ ├── checklist_header.xml │ │ ├── checklist_item.xml │ │ ├── checklist_progress.xml │ │ ├── checklist_view.xml │ │ ├── difficulty_item_view.xml │ │ ├── difficulty_spinner_view.xml │ │ ├── difficulty_view.xml │ │ ├── empty_view.xml │ │ ├── feed_empty_view.xml │ │ ├── feed_header.xml │ │ ├── feed_interval_dialog.xml │ │ ├── feed_item_view.xml │ │ ├── feed_location_dialog.xml │ │ ├── feed_settings_view.xml │ │ ├── feed_view.xml │ │ ├── form_host_view.xml │ │ ├── form_progress.xml │ │ ├── form_view.xml │ │ ├── fragment_standard.xml │ │ ├── head_section.xml │ │ ├── host_checklist.xml │ │ ├── host_reader_view.xml │ │ ├── host_segment_view.xml │ │ ├── lesson_decorator_line.xml │ │ ├── lesson_menu_head.xml │ │ ├── lesson_menu_item.xml │ │ ├── lesson_view.xml │ │ ├── login_view.xml │ │ ├── main_view.xml │ │ ├── mask_app_info_view.xml │ │ ├── pathways.xml │ │ ├── pathways_item.xml │ │ ├── progress_dialog.xml │ │ ├── rss_item_view.xml │ │ ├── rss_view.xml │ │ ├── searching_view.xml │ │ ├── segment_detail.xml │ │ ├── segment_foot.xml │ │ ├── segment_item.xml │ │ ├── segment_view.xml │ │ ├── settings_export_dialog.xml │ │ ├── shake_device.xml │ │ ├── share_dialog.xml │ │ ├── simple_article_view.xml │ │ ├── spinner_text_view.xml │ │ ├── switch_language_alert.xml │ │ ├── switch_repo_alert.xml │ │ ├── tour_alert.xml │ │ ├── tour_view.xml │ │ └── web_view.xml │ │ ├── menu │ │ ├── article_menu.xml │ │ ├── form_menu.xml │ │ ├── login_menu.xml │ │ ├── navigation.xml │ │ ├── option_menu.xml │ │ ├── rss_menu.xml │ │ └── search_menu.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_umbrella.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_umbrella.png │ │ ├── mipmap-xhdpi │ │ ├── calc.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_umbrella.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_umbrella.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_umbrella.png │ │ ├── values-ar │ │ └── strings.xml │ │ ├── values-es │ │ └── strings.xml │ │ ├── values-fa │ │ └── strings.xml │ │ ├── values-fr │ │ └── strings.xml │ │ ├── values-ru │ │ └── strings.xml │ │ ├── values-zh-rKH │ │ └── strings.xml │ │ ├── values-zh-rTW │ │ └── strings.xml │ │ ├── values-zh │ │ └── strings.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── filepaths.xml │ └── test │ ├── java │ └── org │ │ └── secfirst │ │ └── umbrella │ │ ├── form │ │ └── FormPresenterTest.kt │ │ └── storage │ │ ├── FakeTentRepository.kt │ │ ├── TentConfigTest.kt │ │ └── TentDaoTest.kt │ └── resources │ └── mockito-extensions │ └── org.mockito.plugins.MockMaker ├── build.gradle ├── building ├── 02.png ├── 04-2.png ├── 04.png ├── 06-1.png ├── 06-2.png ├── 06.png ├── 09-2.png ├── 09.png ├── 10-2.png ├── 10.png ├── 7.png └── 8.png ├── code_of_conduct.md ├── gradle.properties ├── gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew.bat └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── howtouse.gif └── settings.gradle /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/android:api-28-alpha 6 | environment: 7 | ANDROID_HOME: "/opt/android/sdk" 8 | JAVA_OPTIONS: "-Xms512m -Xmx3200m" 9 | steps: 10 | - checkout 11 | - restore_cache: 12 | keys: 13 | - v1-dependencies-{{ checksum "build.gradle" }} 14 | - v1-dependencies- 15 | 16 | - run: ./gradlew dependencies 17 | 18 | - save_cache: 19 | paths: 20 | - ~/.gradle 21 | key: v1-dependencies-{{ checksum "build.gradle" }} 22 | 23 | - run: echo $BETA_KEYSTORE_BASE64 | base64 -d > app/config/beta_keystore.jks 24 | # Uncomment this when tests get fixed 25 | # - run: 26 | # name: Run Unit Tests 27 | # command: ./gradlew test 28 | - run: 29 | name: Build 30 | command: ./gradlew assemble -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | /.idea/ 11 | .idea/caches/build_file_checksums.ser 12 | .idea/gradle.xml 13 | .idea/misc.xml 14 | app/debug/ 15 | app/config/beta_keystore.keystore 16 | app/beta/ 17 | app/fabric.properties 18 | keystore.properties 19 | *.jks 20 | app/google-services.json 21 | -------------------------------------------------------------------------------- /AMAZON1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/AMAZON1.png -------------------------------------------------------------------------------- /APPSTORE1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/APPSTORE1.png -------------------------------------------------------------------------------- /DASHBOARDLOGOS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/DASHBOARDLOGOS.png -------------------------------------------------------------------------------- /FDROID1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/FDROID1.png -------------------------------------------------------------------------------- /GOOGLEPLAY1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/GOOGLEPLAY1.png -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /.idea 3 | app/beta/ 4 | app/config/ 5 | -------------------------------------------------------------------------------- /app/config/sonarqube.gradle: -------------------------------------------------------------------------------- 1 | sonarqube { 2 | properties { 3 | property "sonar.organization", "douglasalipio-github" 4 | property "sonar.login", "2dd380994315b3f52fb88d40e2f68ccf887355ee" 5 | property "sonar.host.url", "https://sonarcloud.io" 6 | property "sonar.projectKey", "Umbrella_android_kotlin" 7 | property "sonar.projectName", "Umbrella" 8 | property "sonar.projectVersion", "${dependencies}" 9 | property "sonar.sources", "src/main/java" 10 | property "sonar.android.lint.report", "build/outputs/lint-results.xml" 11 | property "sonar.java.binaries", "$buildDir/tmp/kotlin-classes" 12 | property "sonar.jacoco.reportPath", "$buildDir/jacoco/testDebugUnitTest.exec" 13 | property "sonar.junit.reportsPath", "$buildDir/test-results/testDebugUnitTest" 14 | property "detekt.sonar.kotlin.config.id", "/config/detekt-config.yml" 15 | } 16 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class title 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 title. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | # DbFlow 24 | -keep class * extends com.raizlabs.android.dbflow.config.DatabaseHolder { *; } 25 | -keep class * { 26 | public private *; 27 | } 28 | -ignorewarnings 29 | 30 | #DeepLink API 31 | -keep class com.airbnb.deeplinkdispatch.** { *; } 32 | -keepclasseswithmembers class * { 33 | @com.airbnb.deeplinkdispatch.DeepLink ; 34 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/org/secfirst/umbrella/whitelabel/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | import org.junit.Assert.assertEquals 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | 10 | /** 11 | * Instrumented test, which will execute on an Android device. 12 | * 13 | * See [testing documentation](http://d.android.com/tools/testing). 14 | */ 15 | @RunWith(AndroidJUnit4::class) 16 | class ExampleInstrumentedTest { 17 | @Test 18 | fun useAppContext() { 19 | // Context of the app under test. 20 | val appContext = InstrumentationRegistry.getTargetContext() 21 | assertEquals("org.secfirst.umbrella", appContext.packageName) 22 | } 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/org/secfirst/umbrella/whitelabel/misc/CustomAssertions.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.misc 2 | 3 | import android.support.test.espresso.NoMatchingViewException 4 | import android.support.test.espresso.ViewAssertion 5 | import android.support.test.espresso.matcher.ViewMatchers.assertThat 6 | import android.support.v7.widget.RecyclerView 7 | import android.view.View 8 | import org.hamcrest.CoreMatchers 9 | 10 | class CustomAssertions { 11 | companion object { 12 | fun hasItemCount(count: Int): ViewAssertion { 13 | return RecyclerViewItemCountAssertion(count) 14 | } 15 | } 16 | 17 | private class RecyclerViewItemCountAssertion(private val count: Int) : ViewAssertion { 18 | override fun check(view: View, noViewFoundException: NoMatchingViewException?) { 19 | if (noViewFoundException != null) { 20 | throw noViewFoundException 21 | } 22 | 23 | if (view !is RecyclerView) { 24 | throw IllegalStateException("The asserted view is not RecyclerView") 25 | } 26 | 27 | if (view.adapter == null) { 28 | throw IllegalStateException("No adapter is assigned to RecyclerView") 29 | } 30 | 31 | assertThat("RecyclerView item count", view.adapter.itemCount, CoreMatchers.equalTo(count)) 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/org/secfirst/umbrella/whitelabel/misc/CustomMatchers.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.misc 2 | 3 | import android.support.test.espresso.matcher.BoundedMatcher 4 | import android.support.v7.widget.RecyclerView 5 | import android.view.View 6 | import org.hamcrest.Description 7 | import org.hamcrest.Matcher 8 | 9 | class CustomMatchers { 10 | companion object { 11 | fun withItemCount(count: Int): Matcher { 12 | return object : BoundedMatcher(RecyclerView::class.java) { 13 | override fun describeTo(description: Description?) { 14 | description?.appendText("RecyclerView with item count: $count") 15 | } 16 | 17 | override fun matchesSafely(item: RecyclerView?): Boolean { 18 | return item?.adapter?.itemCount == count 19 | } 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/assets/default_rss.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "link": "https://threatpost.com/feed/" 5 | }, 6 | { 7 | "link": "https://krebsonsecurity.com/feed/" 8 | }, 9 | { 10 | "link": "http://feeds.bbci.co.uk/news/world/rss.xml?edition=uk" 11 | }, 12 | { 13 | "link": "http://rss.cnn.com/rss/edition.rss" 14 | }, 15 | { 16 | "link": "https://www.aljazeera.com/xml/rss/all.xml" 17 | }, 18 | { 19 | "link": "https://www.theguardian.com/world/rss" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/assets/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/assets/fonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /app/src/main/assets/fonts/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/assets/fonts/Roboto-Regular.ttf -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/component/AutoFitGridLayoutManager.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.component 2 | 3 | import android.content.Context 4 | import androidx.recyclerview.widget.GridLayoutManager 5 | import androidx.recyclerview.widget.LinearLayoutManager 6 | import androidx.recyclerview.widget.RecyclerView 7 | 8 | 9 | class AutoFitGridLayoutManager(context: Context, private var columnWidth: Int) : GridLayoutManager(context, columnWidth) { 10 | 11 | private var columnWidthChanged = true 12 | 13 | fun setColumnWidth(newColumnWidth: Int) { 14 | if (newColumnWidth > 0 && newColumnWidth != columnWidth) { 15 | columnWidth = newColumnWidth 16 | columnWidthChanged = true 17 | } 18 | } 19 | 20 | override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State) { 21 | if (columnWidthChanged && columnWidth > 0) { 22 | val totalSpace: Int = if (orientation == LinearLayoutManager.VERTICAL) { 23 | width - paddingRight - paddingLeft 24 | } else { 25 | height - paddingTop - paddingBottom 26 | } 27 | val spanCount = Math.max(1, totalSpace / columnWidth) 28 | setSpanCount(spanCount) 29 | columnWidthChanged = false 30 | } 31 | super.onLayoutChildren(recycler, state) 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/component/RefreshIntervalDialog.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.component 2 | 3 | import android.app.AlertDialog 4 | import android.view.View 5 | import kotlinx.android.synthetic.main.alert_control.view.* 6 | import kotlinx.android.synthetic.main.feed_interval_dialog.view.* 7 | import org.secfirst.umbrella.R 8 | 9 | class RefreshIntervalDialog(private val view: View, private val initialInterval: String, 10 | private val listener: RefreshIntervalListener) { 11 | 12 | private val refreshIntervalDialog = AlertDialog 13 | .Builder(view.context) 14 | .setView(view) 15 | .create() 16 | 17 | 18 | init { 19 | view.alertControlOk.setOnClickListener { refreshIntervalOk() } 20 | view.alertControlCancel.setOnClickListener { refreshIntervalCancel() } 21 | } 22 | 23 | fun show() { 24 | refreshIntervalDialog.show() 25 | } 26 | 27 | private fun refreshIntervalOk() { 28 | val selectedInterval = view.feedInterval.text.toString() 29 | refreshIntervalDialog.dismiss() 30 | listener.onRefreshIntervalSuccess(selectedInterval) 31 | } 32 | 33 | private fun refreshIntervalCancel() { 34 | listener.onRefreshIntervalCancel() 35 | refreshIntervalDialog.dismiss() 36 | } 37 | 38 | interface RefreshIntervalListener { 39 | fun onRefreshIntervalSuccess(selectedInterval: String) 40 | fun onRefreshIntervalCancel() {} 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/VirtualStorage.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data 2 | 3 | import android.app.Application 4 | import info.guardianproject.iocipher.VirtualFileSystem 5 | import kotlinx.coroutines.withContext 6 | import org.secfirst.umbrella.misc.AppExecutors 7 | import java.io.BufferedWriter 8 | import java.io.File 9 | import java.io.FileWriter 10 | import javax.inject.Inject 11 | 12 | 13 | class VirtualStorage @Inject constructor(private val application: Application) { 14 | 15 | suspend fun mountFilesystem(document: String, fileName: String): File { 16 | val file = File(application.cacheDir, "$fileName.html") 17 | withContext(AppExecutors.ioContext) { 18 | if (!file.exists()) file.createNewFile() 19 | val virtualSystem = VirtualFileSystem.get() 20 | virtualSystem.containerPath = file.path 21 | if (!virtualSystem.isMounted) virtualSystem.mount("password") 22 | if (!virtualSystem.isMounted) virtualSystem.createNewContainer(file.path, "password") 23 | } 24 | return write(file, document) 25 | } 26 | 27 | private fun write(file: File, document: String): File { 28 | val writer = BufferedWriter(FileWriter(file)) 29 | writer.write(document) 30 | writer.flush() 31 | writer.close() 32 | return file 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/AppDatabase.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database 2 | 3 | import com.raizlabs.android.dbflow.annotation.Database 4 | 5 | @Database(version = AppDatabase.VERSION, 6 | generatedClassSeparator = "_", 7 | foreignKeyConstraintsEnforced = true) 8 | 9 | object AppDatabase { 10 | 11 | const val DEFAULT = "umbrella" 12 | const val NAME = "umbrella_database" 13 | const val VERSION = 1 14 | const val EXTENSION = "db" 15 | } 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/SQLCipherHelperImpl.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database 2 | 3 | import com.raizlabs.android.dbflow.config.DatabaseDefinition 4 | import com.raizlabs.android.dbflow.sqlcipher.SQLCipherOpenHelper 5 | import com.raizlabs.android.dbflow.structure.database.DatabaseHelperListener 6 | import org.secfirst.umbrella.data.database.AppDatabase.DEFAULT 7 | 8 | 9 | class SQLCipherHelperImpl( 10 | databaseDefinition: DatabaseDefinition, 11 | databaseHelperListener: DatabaseHelperListener?, 12 | private val userToken: String? = null) : SQLCipherOpenHelper(databaseDefinition, databaseHelperListener) { 13 | 14 | override fun getCipherSecret(): String { 15 | return userToken ?: DEFAULT 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/account/AccountRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.account 2 | 3 | import org.secfirst.umbrella.data.database.reader.FeedLocation 4 | import org.secfirst.umbrella.data.database.reader.FeedSource 5 | 6 | interface AccountRepo { 7 | 8 | suspend fun loginDatabase(userToken: String) 9 | 10 | suspend fun changeToken(userToken: String): Boolean 11 | 12 | suspend fun getFeedLocation(): FeedLocation? 13 | 14 | suspend fun getAllFeedSources(): List 15 | 16 | suspend fun saveAllFeedSources(feedSources: List) 17 | 18 | suspend fun saveFeedLocation(feedLocation: FeedLocation) 19 | 20 | suspend fun wipeMainContent() : Boolean 21 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/account/AccountRepository.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.account 2 | 3 | import org.secfirst.umbrella.data.database.reader.FeedLocation 4 | import org.secfirst.umbrella.data.database.reader.FeedSource 5 | import javax.inject.Inject 6 | 7 | class AccountRepository @Inject constructor(private val accountDao: AccountDao) : AccountRepo { 8 | 9 | override suspend fun wipeMainContent() = accountDao.deleteMainContent() 10 | 11 | override suspend fun loginDatabase(userToken: String) = accountDao.initDatabase(userToken) 12 | 13 | override suspend fun changeToken(userToken: String) = accountDao.changeDatabaseAccess(userToken) 14 | 15 | override suspend fun saveFeedLocation(feedLocation: FeedLocation) = accountDao.saveFeedLocation(feedLocation) 16 | 17 | override suspend fun saveAllFeedSources(feedSources: List) = accountDao.saveAllFeedSource(feedSources) 18 | 19 | override suspend fun getFeedLocation() = accountDao.getFeedLocation() 20 | 21 | override suspend fun getAllFeedSources() = accountDao.getAllFeedSource() 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/checklist/ChecklistRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.checklist 2 | 3 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 4 | import org.secfirst.umbrella.data.database.lesson.Module 5 | import org.secfirst.umbrella.data.database.lesson.Subject 6 | 7 | interface ChecklistRepo { 8 | 9 | suspend fun deleteChecklistContent(checklistContent: Content) 10 | 11 | suspend fun deleteChecklist(checklist: Checklist) 12 | 13 | suspend fun disableChecklistContent(checklistContent: Content) 14 | 15 | suspend fun insertChecklistContent(checklistContent: Content) 16 | 17 | suspend fun insertChecklist(checklist: Checklist) 18 | 19 | suspend fun loadAllChecklistFavorite(): List 20 | 21 | suspend fun loadChecklistCount(): Long 22 | 23 | suspend fun loadAllChecklist(): List 24 | 25 | suspend fun loadSubjectById(subjectId: String): Subject? 26 | 27 | suspend fun loadDifficultyById(difficultyId: String): Difficulty? 28 | 29 | suspend fun loadAllChecklistInProgress(): List 30 | 31 | suspend fun loadAllCustomChecklistInProgress(): List 32 | 33 | suspend fun loadChecklist(checklistId: String): Checklist? 34 | 35 | suspend fun loadModule(moduleName: String): Module? 36 | 37 | suspend fun loadAllPathways(): List 38 | 39 | suspend fun loadFavoritePathways() : List 40 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/content/ContentRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.content 2 | 3 | import org.secfirst.umbrella.data.database.checklist.Checklist 4 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 5 | import org.secfirst.umbrella.data.database.form.Form 6 | import org.secfirst.umbrella.data.database.lesson.Module 7 | import org.secfirst.umbrella.data.database.lesson.Subject 8 | import org.secfirst.umbrella.data.database.reader.FeedSource 9 | import org.secfirst.umbrella.data.database.reader.RSS 10 | import org.secfirst.umbrella.data.database.segment.Markdown 11 | 12 | 13 | interface ContentRepo { 14 | 15 | suspend fun insertAllLessons(contentData: ContentData) 16 | 17 | suspend fun insertFeedSource(feedSources: List) 18 | 19 | suspend fun insertDefaultRSS(rssList: List) 20 | 21 | suspend fun saveAllChecklists(checklists: List) 22 | 23 | suspend fun saveAllMarkdowns(markdowns: List) 24 | 25 | suspend fun saveAllModule(modules: List) 26 | 27 | suspend fun saveAllDifficulties(difficulties: List) 28 | 29 | suspend fun saveAllForms(forms: List
) 30 | 31 | suspend fun saveAllSubjects(subjects: List) 32 | 33 | suspend fun getSubject(subjectId: String): Subject? 34 | 35 | suspend fun getDifficulty(difficultyId: String): Difficulty? 36 | 37 | suspend fun getModule(moduleId: String): Module? 38 | 39 | suspend fun getMarkdown(markdownId: String): Markdown? 40 | 41 | suspend fun getChecklist(checklistId: String): Checklist? 42 | 43 | suspend fun getForm(formId: String): Form? 44 | 45 | suspend fun resetContent() : Boolean 46 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/difficulty/DifficultyDao.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.difficulty 2 | 3 | import com.raizlabs.android.dbflow.kotlinextensions.modelAdapter 4 | import com.raizlabs.android.dbflow.sql.language.SQLite 5 | import kotlinx.coroutines.withContext 6 | import org.secfirst.umbrella.data.database.lesson.Subject 7 | import org.secfirst.umbrella.data.database.lesson.Subject_Table 8 | import org.secfirst.umbrella.misc.AppExecutors 9 | 10 | interface DifficultyDao { 11 | 12 | suspend fun save(difficultyPreferred: DifficultyPreferred) { 13 | withContext(AppExecutors.ioContext) { 14 | modelAdapter().save(difficultyPreferred) 15 | } 16 | } 17 | 18 | suspend fun getSubjectByModule(modulePathId: String): Subject? = withContext(AppExecutors.ioContext) { 19 | SQLite.select() 20 | .from(Subject::class.java) 21 | .where(Subject_Table.module_id.`is`(modulePathId)) 22 | .querySingle() 23 | } 24 | 25 | suspend fun getSubjectBy(subjectPathId: String): Subject? = withContext(AppExecutors.ioContext) { 26 | SQLite.select() 27 | .from(Subject::class.java) 28 | .where(Subject_Table.id.`is`(subjectPathId)) 29 | .querySingle() 30 | } 31 | 32 | suspend fun getDifficultyBy(pathId: String): Difficulty? = withContext(AppExecutors.ioContext) { 33 | SQLite.select() 34 | .from(Difficulty::class.java) 35 | .where(Difficulty_Table.id.`is`(pathId)) 36 | .querySingle() 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/difficulty/DifficultyRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.difficulty 2 | 3 | import org.secfirst.umbrella.data.database.lesson.Subject 4 | 5 | interface DifficultyRepo { 6 | 7 | suspend fun loadDifficultyBy(sha1ID: String): Difficulty? 8 | 9 | suspend fun loadSubjectBy(subjectSha1ID: String): Subject? 10 | 11 | suspend fun loadSubjectByModule(moduleSha1ID: String): Subject? 12 | 13 | suspend fun saveTopicPreferred(difficultyPreferred: DifficultyPreferred) 14 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/difficulty/DifficultyRepository.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.difficulty 2 | 3 | import javax.inject.Inject 4 | 5 | class DifficultyRepository @Inject constructor(private val diffDao: DifficultyDao) : DifficultyRepo { 6 | 7 | override suspend fun loadSubjectByModule(moduleSha1ID: String) = diffDao.getSubjectByModule(moduleSha1ID) 8 | 9 | override suspend fun loadDifficultyBy(sha1ID: String) = diffDao.getDifficultyBy(sha1ID) 10 | 11 | override suspend fun loadSubjectBy(subjectSha1ID: String) = diffDao.getSubjectBy(subjectSha1ID) 12 | 13 | override suspend fun saveTopicPreferred(difficultyPreferred: DifficultyPreferred) = diffDao.save(difficultyPreferred) 14 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/form/FormRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.form 2 | 3 | interface FormRepo { 4 | 5 | suspend fun removeActiveForm(activeForm: ActiveForm) 6 | 7 | suspend fun persistFormData(answer: Answer) 8 | 9 | suspend fun persistActiveForm(activeForm: ActiveForm): Boolean 10 | 11 | suspend fun loadModelForms(): List 12 | 13 | suspend fun loadAnswerBy(formId: Long): List 14 | 15 | suspend fun loadActiveForms(): List 16 | 17 | suspend fun loadForm(formTitle: String): Form? 18 | 19 | suspend fun loadScreenBy(sh1ID : String): List 20 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/form/FormRepository.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.form 2 | 3 | import javax.inject.Inject 4 | 5 | class FormRepository @Inject constructor(private val formDao: FormDao) : FormRepo { 6 | 7 | override suspend fun loadForm(formTitle: String) = formDao.getForm(formTitle) 8 | 9 | override suspend fun removeActiveForm(activeForm: ActiveForm) = formDao.delete(activeForm) 10 | 11 | override suspend fun loadScreenBy(sh1ID: String): List = formDao.getScreenBy(sh1ID) 12 | 13 | override suspend fun persistActiveForm(activeForm: ActiveForm) = formDao.saveActiveForm(activeForm) 14 | 15 | override suspend fun persistFormData(answer: Answer) = formDao.insertAnswer(answer) 16 | 17 | override suspend fun loadModelForms() = formDao.getAllFormModel() 18 | 19 | override suspend fun loadAnswerBy(formId: Long) = formDao.getAnswerBy(formId) 20 | 21 | override suspend fun loadActiveForms(): List = formDao.getAllActiveForms() 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/lesson/LessonRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.lesson 2 | 3 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 4 | import org.secfirst.umbrella.data.database.difficulty.DifficultyPreferred 5 | import org.secfirst.umbrella.data.database.segment.Markdown 6 | 7 | interface LessonRepo { 8 | 9 | suspend fun loadAllModules(): List 10 | 11 | suspend fun loadLessonBy(moduleId: String): Module? 12 | 13 | suspend fun loadMarkdownBySubject(subjectId: String): List 14 | 15 | suspend fun loadDifficultyBySubject(subjectId: String): List 16 | 17 | suspend fun loadAllFavoriteSubjects(): List 18 | 19 | suspend fun loadDifficultyPreferredBy(subjectId: String): DifficultyPreferred? 20 | 21 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/lesson/LessonRepository.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.lesson 2 | 3 | import javax.inject.Inject 4 | 5 | class LessonRepository @Inject constructor(private val lessonDao: LessonDao) : LessonRepo { 6 | 7 | override suspend fun loadDifficultyBySubject(subjectId: String) = lessonDao.getDifficultyBySubject(subjectId) 8 | 9 | override suspend fun loadAllFavoriteSubjects() = lessonDao.getFavoriteMarkdown() 10 | 11 | override suspend fun loadMarkdownBySubject(subjectId: String) = lessonDao.getMarkdownBySubject(subjectId) 12 | 13 | override suspend fun loadLessonBy(sha1ID: String) = lessonDao.getLessonBy(sha1ID) 14 | 15 | override suspend fun loadDifficultyPreferredBy(subjectId: String) = lessonDao.getDifficultyPreferred(subjectId) 16 | 17 | override suspend fun loadAllModules() = lessonDao.getAllLesson() 18 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/login/LoginDao.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.login 2 | 3 | import org.secfirst.umbrella.data.database.BaseDao 4 | 5 | interface LoginDao : BaseDao -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/login/LoginRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.login 2 | 3 | interface LoginRepo { 4 | 5 | fun loginDatabase(userToken: String) 6 | 7 | suspend fun changeToken(userToken: String): Boolean 8 | 9 | fun verifyDatabaseIntegrity() : Boolean 10 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/login/LoginRepository.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.login 2 | 3 | import javax.inject.Inject 4 | 5 | class LoginRepository @Inject constructor(private val loginDao: LoginDao) : LoginRepo { 6 | 7 | override fun verifyDatabaseIntegrity() = loginDao.isDatabaseOK() 8 | 9 | override fun loginDatabase(userToken: String) = loginDao.initDatabase(userToken) 10 | 11 | override suspend fun changeToken(userToken: String) = loginDao.changeDatabaseAccess(userToken) 12 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/reader/ReaderRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.reader 2 | 3 | interface ReaderRepo { 4 | 5 | suspend fun saveRss(rss: RSS) 6 | 7 | suspend fun saveFeedLocation(feedLocation: FeedLocation) 8 | 9 | suspend fun deleteLocation() 10 | 11 | suspend fun saveAllRss(rssList: List) 12 | 13 | suspend fun saveAllFeedSources(feedSources: List) 14 | 15 | suspend fun delete(rss: RSS): Boolean 16 | 17 | suspend fun getAllRss(): List 18 | 19 | suspend fun getFeedLocation(): FeedLocation? 20 | 21 | suspend fun getAllFeedSources(): List 22 | 23 | suspend fun changeToken(userToken: String): Boolean 24 | 25 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/reader/ReaderRepository.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.reader 2 | 3 | import javax.inject.Inject 4 | 5 | class ReaderRepository @Inject constructor(private val readerDao: ReaderDao) : ReaderRepo { 6 | 7 | override suspend fun changeToken(userToken: String) = readerDao.changeDatabaseAccess(userToken) 8 | 9 | override suspend fun deleteLocation() = readerDao.deleteLocation() 10 | 11 | override suspend fun saveFeedLocation(feedLocation: FeedLocation) = readerDao.saveFeedLocation(feedLocation) 12 | 13 | override suspend fun saveAllFeedSources(feedSources: List) = readerDao.saveAllFeedSource(feedSources) 14 | 15 | override suspend fun getFeedLocation() = readerDao.getFeedLocation() 16 | 17 | override suspend fun getAllFeedSources() = readerDao.getAllFeedSource() 18 | 19 | override suspend fun saveAllRss(rssList: List) = readerDao.saveAllRss(rssList) 20 | 21 | override suspend fun delete(rss: RSS) = readerDao.delete(rss) 22 | 23 | override suspend fun saveRss(rss: RSS) = readerDao.saveRss(rss) 24 | 25 | override suspend fun getAllRss() = readerDao.getAllRss() 26 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/segment/SegmentRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.segment 2 | 3 | import org.secfirst.umbrella.data.database.checklist.Checklist 4 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 5 | import org.secfirst.umbrella.data.database.lesson.Module 6 | import org.secfirst.umbrella.data.database.lesson.Subject 7 | 8 | interface SegmentRepo { 9 | 10 | suspend fun loadChecklist(checklistId: String): Checklist? 11 | 12 | suspend fun loadMarkdown(markdownId: String): Markdown? 13 | 14 | suspend fun loadSubject(subjectId: String): Subject? 15 | 16 | suspend fun loadModule(moduleId: String): Module? 17 | 18 | suspend fun loadDifficulty(difficultyId: String): Difficulty? 19 | 20 | suspend fun saveChecklist(checklist: Checklist) 21 | 22 | suspend fun saveMarkdown(markdown: Markdown) 23 | 24 | suspend fun saveDifficultySelect(subjectId: String, difficulty: Difficulty) 25 | 26 | suspend fun loadDifficultyBySubjectId(subjectId: String): List 27 | 28 | suspend fun loadSubjectByRootDir(rootDir: String): Subject? 29 | 30 | suspend fun loadModuleByRootdir(moduleName: String): Module? 31 | 32 | 33 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/database/segment/SegmentRepository.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.database.segment 2 | 3 | import org.secfirst.umbrella.data.database.checklist.Checklist 4 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 5 | import javax.inject.Inject 6 | 7 | class SegmentRepository @Inject constructor(private val segmentDao: SegmentDao) : SegmentRepo { 8 | 9 | override suspend fun loadSubjectByRootDir(rootDir: String) = segmentDao.getSubjectByRootDir(rootDir) 10 | 11 | override suspend fun loadDifficultyBySubjectId(subjectId: String) = segmentDao.getDifficultyBySubjectId(subjectId) 12 | 13 | override suspend fun loadModuleByRootdir(moduleName: String) = segmentDao.getModuleByRootDir(moduleName) 14 | 15 | override suspend fun loadMarkdown(markdownId: String) = segmentDao.getMarkdown(markdownId) 16 | 17 | override suspend fun loadChecklist(checklistId: String) = segmentDao.getChecklist(checklistId) 18 | 19 | override suspend fun loadDifficulty(difficultyId: String) = segmentDao.getDifficulty(difficultyId) 20 | 21 | override suspend fun saveDifficultySelect(subjectId: String, difficulty: Difficulty) = segmentDao.save(subjectId, difficulty) 22 | 23 | override suspend fun saveMarkdown(markdown: Markdown) = segmentDao.save(markdown) 24 | 25 | override suspend fun saveChecklist(checklist: Checklist) = segmentDao.save(checklist) 26 | 27 | override suspend fun loadModule(moduleId: String) = segmentDao.getModule(moduleId) 28 | 29 | override suspend fun loadSubject(subjectId: String) = segmentDao.getSubject(subjectId) 30 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/disk/TentRepo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.disk 2 | 3 | import java.io.File 4 | 5 | 6 | interface TentRepo { 7 | 8 | suspend fun fetchRepository(url: String): Boolean 9 | 10 | suspend fun updateRepository(): List> 11 | 12 | suspend fun loadElementsFile(path : String): List 13 | 14 | fun loadFormFile(path : String): List 15 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/disk/TentRepository.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.disk 2 | 3 | import java.io.File 4 | import javax.inject.Inject 5 | 6 | class TentRepository @Inject constructor(private val tentDao: TentDao) : TentRepo { 7 | 8 | 9 | override fun loadFormFile(path : String): List = tentDao.filterForms(path) 10 | 11 | override suspend fun updateRepository() = tentDao.rebaseBranch() 12 | 13 | override suspend fun loadElementsFile(path : String) = tentDao.filterCategories(path) 14 | 15 | override suspend fun fetchRepository(url: String) = tentDao.cloneRepository(url) 16 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/network/NetworkDataObj.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | 6 | @SuppressWarnings 7 | data class Blog(@Expose 8 | @SerializedName("blog_url") 9 | var blogUrl: String? = null, 10 | 11 | @Expose 12 | @SerializedName("img_url") 13 | var coverImgUrl: String? = null, 14 | 15 | @Expose 16 | @SerializedName("title") 17 | var title: String? = null, 18 | 19 | @Expose 20 | @SerializedName("description") 21 | var description: String? = null, 22 | 23 | @Expose 24 | @SerializedName("author") 25 | var author: String? = null, 26 | 27 | @Expose 28 | @SerializedName("published_at") 29 | var date: String? = null) -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/network/NetworkEndPoint.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.network 2 | 3 | object NetworkEndPoint { 4 | const val BASE_URL = "https://api.secfirst.org/" 5 | const val FEED_LIST = "v3/feed?" 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/network/NetworkHelper.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.network 2 | 3 | import com.google.gson.annotations.Expose 4 | import com.google.gson.annotations.SerializedName 5 | import kotlinx.coroutines.Deferred 6 | import okhttp3.ResponseBody 7 | import org.secfirst.umbrella.di.ApiKeyInfo 8 | import retrofit2.http.GET 9 | import retrofit2.http.Query 10 | import retrofit2.http.Url 11 | import javax.inject.Inject 12 | 13 | /** 14 | * Just define possible header for requests. 15 | */ 16 | class ApiHeader @Inject constructor(internal val publicApiHeader: PublicApiHeader) { 17 | 18 | class PublicApiHeader @Inject constructor(@ApiKeyInfo 19 | @Expose 20 | @SerializedName 21 | ("api_key") val apiKey: String) 22 | } 23 | 24 | /** 25 | * Responsible to tracking all API calls. 26 | */ 27 | interface ApiHelper { 28 | 29 | @GET(NetworkEndPoint.FEED_LIST) 30 | fun getBlogApiCall(): Deferred 31 | 32 | @GET(NetworkEndPoint.FEED_LIST) 33 | @Wrapped 34 | fun getFeedList(@Query("country") countryCode: String, 35 | @Query("sources") sources: String, 36 | @Query("since") since: String): Deferred 37 | 38 | @GET 39 | fun getRss(@Url url: String): Deferred 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/data/network/NetworkReponse.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.data.network 2 | 3 | import android.os.Parcelable 4 | import com.google.gson.annotations.Expose 5 | import com.google.gson.annotations.SerializedName 6 | import com.squareup.moshi.Json 7 | import com.squareup.moshi.JsonQualifier 8 | import kotlinx.android.parcel.Parcelize 9 | 10 | 11 | @Suppress("MatchingDeclarationName") 12 | data class BlogResponse(@Expose 13 | @SerializedName("status_code") 14 | private var statusCode: String? = null, 15 | 16 | @Expose 17 | @SerializedName("message") 18 | private var message: String? = null, 19 | 20 | @Expose 21 | @SerializedName("date") 22 | var data: List? = null) 23 | 24 | @Parcelize 25 | data class FeedItemResponse( 26 | @SerializedName("title") 27 | var title: String = "", 28 | @SerializedName("description") 29 | var description: String = "", 30 | @SerializedName("url") 31 | var url: String = "", 32 | @field:Json(name = "") 33 | @SerializedName("updated_at") 34 | var updatedAt: Long = 0) : Parcelable 35 | 36 | @Retention(AnnotationRetention.RUNTIME) 37 | @JsonQualifier 38 | annotation class Wrapped 39 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/di/ApiKeyInfo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.di 2 | 3 | import javax.inject.Qualifier 4 | 5 | 6 | @Qualifier 7 | @Retention 8 | annotation class ApiKeyInfo 9 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/di/PreferenceInfo.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.di 2 | 3 | import javax.inject.Qualifier 4 | 5 | @Qualifier 6 | @Retention 7 | annotation class PreferenceInfo 8 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/di/builder/ActivityBuilder.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.di.builder 2 | 3 | import dagger.Module 4 | import dagger.android.ContributesAndroidInjector 5 | import org.secfirst.umbrella.feature.main.MainActivity 6 | 7 | 8 | @Module 9 | abstract class ActivityBuilder { 10 | 11 | //@ContributesAndroidInjector(modules = [(MainAtivityModule::class)]) 12 | @ContributesAndroidInjector() 13 | abstract fun bindBaseActivity(): MainActivity 14 | } 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/di/component/AppComponent.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.di.component 2 | 3 | import android.app.Application 4 | import dagger.BindsInstance 5 | import dagger.Component 6 | import dagger.android.AndroidInjectionModule 7 | import org.secfirst.umbrella.UmbrellaApplication 8 | import org.secfirst.umbrella.di.builder.ActivityBuilder 9 | import org.secfirst.umbrella.di.module.AppModule 10 | import org.secfirst.umbrella.di.module.NetworkModule 11 | import org.secfirst.umbrella.di.module.RepositoryModule 12 | import org.secfirst.umbrella.di.module.TentContentModule 13 | import javax.inject.Singleton 14 | 15 | @Singleton 16 | @Component(modules = [(AndroidInjectionModule::class), 17 | (AppModule::class), 18 | (RepositoryModule::class), 19 | (NetworkModule::class), 20 | (TentContentModule::class), 21 | (ActivityBuilder::class)]) 22 | 23 | interface AppComponent { 24 | 25 | @Component.Builder 26 | interface Builder { 27 | 28 | @BindsInstance 29 | fun application(application: Application): Builder 30 | 31 | fun build(): AppComponent 32 | } 33 | 34 | fun inject(app: UmbrellaApplication) 35 | 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/account/interactor/AccountBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.account.interactor 2 | 3 | import org.secfirst.umbrella.data.database.reader.FeedLocation 4 | import org.secfirst.umbrella.data.database.reader.FeedSource 5 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 6 | 7 | interface AccountBaseInteractor : BaseInteractor { 8 | 9 | suspend fun accessDatabase(userToken: String) 10 | 11 | suspend fun changeDatabaseAccess(userToken: String): Boolean 12 | 13 | suspend fun insertFeedLocation(feedLocation: FeedLocation) 14 | 15 | suspend fun insertAllFeedSources(feedSources: List) 16 | 17 | suspend fun fetchFeedSources(): List 18 | 19 | suspend fun fetchFeedLocation(): FeedLocation? 20 | 21 | suspend fun fetchRefreshInterval(): Int 22 | 23 | suspend fun putRefreshInterval(position: Int): Boolean 24 | 25 | fun setMaskApp(value: Boolean): Boolean 26 | 27 | fun isMaskApp(): Boolean 28 | 29 | fun setFakeView(isShowFakeView: Boolean) : Boolean 30 | 31 | fun getMaskApp() : Boolean 32 | 33 | suspend fun serializeNewContent(path : String) : Boolean 34 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/account/presenter/AccountBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.account.presenter 2 | 3 | import org.secfirst.umbrella.data.database.reader.FeedLocation 4 | import org.secfirst.umbrella.data.database.reader.FeedSource 5 | import org.secfirst.umbrella.feature.account.interactor.AccountBaseInteractor 6 | import org.secfirst.umbrella.feature.account.view.AccountView 7 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 8 | 9 | interface AccountBasePresenter : BasePresenter { 10 | 11 | fun submitChangeDatabaseAccess(userToken: String) 12 | 13 | fun submitExportDatabase(destinationDir: String, fileName: String, isWipeData: Boolean) 14 | 15 | fun setUserLogIn() 16 | 17 | fun setSkipPassword(value: Boolean) 18 | 19 | fun submitSkippPassword() 20 | 21 | fun prepareShareContent(fileName: String) 22 | 23 | fun validateBackupPath(backupPath: String) 24 | 25 | fun submitInsertFeedSource(feedSources: List) 26 | 27 | fun submitFeedLocation(feedLocation: FeedLocation) 28 | 29 | fun prepareView() 30 | 31 | fun submitPutRefreshInterval(position: Int) 32 | 33 | fun setMaskApp(value: Boolean) 34 | 35 | fun submitIsLogged() 36 | 37 | fun submitCleanDatabase() 38 | 39 | fun switchServerProcess(repoUrl: String) 40 | 41 | fun submitDefaultLanguage() 42 | 43 | fun setDefaultLanguage(isoCountry : String) 44 | 45 | fun submitFakeView(isShowFakeView : Boolean) 46 | 47 | fun submitIsMaskApp() 48 | 49 | fun changeContentLanguage(path : String) 50 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/account/view/AccountView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.account.view 2 | 3 | import org.secfirst.umbrella.data.database.reader.FeedLocation 4 | import org.secfirst.umbrella.data.database.reader.FeedSource 5 | import org.secfirst.umbrella.feature.base.view.BaseView 6 | import java.io.File 7 | 8 | interface AccountView : BaseView { 9 | 10 | fun isUserLogged(res: Boolean) {} 11 | 12 | fun isTokenChanged(res: Boolean) {} 13 | 14 | fun exportDatabaseSuccessfully() {} 15 | 16 | fun onShareContent(backupFile: File) {} 17 | 18 | fun onImportBackupSuccess() {} 19 | 20 | fun onImportBackupFail() {} 21 | 22 | fun loadDefaultValue(feedLocation: FeedLocation?, refreshFeedInterval: Int, feedSource: List) {} 23 | 24 | fun onSwitchServer(isSwitch: Boolean) {} 25 | 26 | fun getSkipPassword(res: Boolean) {} 27 | 28 | fun onResetContent(res: Boolean) {} 29 | 30 | fun getDefaultLanguage(isoCountry: String){} 31 | 32 | fun getMaskApp(isMaskApp : Boolean){} 33 | 34 | fun onChangedLanguageSuccess(){} 35 | 36 | fun onChangedLanguageFail(){} 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/base/interactor/BaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.base.interactor 2 | 3 | interface BaseInteractor { 4 | 5 | fun isUserLoggedIn(): Boolean 6 | 7 | fun setLoggedIn(isLogged: Boolean): Boolean 8 | 9 | fun enablePasswordBanner(enableBanner: Boolean): Boolean 10 | 11 | fun setSkipPassword(isSkip: Boolean): Boolean 12 | 13 | fun isSkippPassword(): Boolean 14 | 15 | fun setDefaultLanguage(isoCountry: String) : Boolean 16 | 17 | fun getDefaultLanguage(): String 18 | 19 | suspend fun resetContent(): Boolean 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/base/presenter/BasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.base.presenter 2 | 3 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 4 | import org.secfirst.umbrella.feature.base.view.BaseView 5 | 6 | interface BasePresenter { 7 | 8 | fun onAttach(view: V?) 9 | 10 | fun onDetach() 11 | 12 | fun getView(): V? 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/base/presenter/BasePresenterImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.base.presenter 2 | 3 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 4 | import org.secfirst.umbrella.feature.base.view.BaseView 5 | 6 | abstract class BasePresenterImp 7 | internal constructor(protected var interactor: I?) : BasePresenter { 8 | 9 | private var view: V? = null 10 | 11 | private val isViewAttached: Boolean get() = view != null 12 | 13 | override fun onAttach(view: V?) { 14 | this.view = view 15 | } 16 | 17 | override fun getView(): V? = view 18 | 19 | override fun onDetach() { 20 | view = null 21 | interactor = null 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/base/view/BaseController.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.base.view 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import android.view.View 6 | import com.bluelinelabs.conductor.Controller 7 | import kotlinx.android.extensions.LayoutContainer 8 | import kotlinx.android.synthetic.* 9 | import org.secfirst.umbrella.feature.main.MainActivity 10 | 11 | abstract class BaseController(bundle: Bundle = Bundle()) : Controller(bundle), LayoutContainer { 12 | 13 | init { 14 | inject() 15 | } 16 | 17 | private fun inject() = onInject() 18 | lateinit var mainActivity: MainActivity 19 | lateinit var context: Context 20 | protected abstract fun onInject() 21 | 22 | override val containerView: View? 23 | get() = view 24 | 25 | override fun onContextAvailable(context: Context) { 26 | this.context = context 27 | activity.let { mainActivity = activity as MainActivity } 28 | super.onContextAvailable(context) 29 | } 30 | 31 | override fun onDestroyView(view: View) { 32 | super.onDestroyView(view) 33 | clearFindViewByIdCache() 34 | } 35 | 36 | fun enableNavigation(isNavigation: Boolean) = 37 | if (isNavigation) mainActivity.showNavigation() else mainActivity.hideNavigation() 38 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/base/view/BaseView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.base.view 2 | 3 | interface BaseView { 4 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/checklist/interactor/ChecklistBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.checklist.interactor 2 | 3 | import org.secfirst.umbrella.data.database.checklist.Checklist 4 | import org.secfirst.umbrella.data.database.checklist.Content 5 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 6 | import org.secfirst.umbrella.data.database.lesson.Module 7 | import org.secfirst.umbrella.data.database.lesson.Subject 8 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 9 | 10 | interface ChecklistBaseInteractor : BaseInteractor { 11 | 12 | suspend fun deleteChecklistContent(checklistContent: Content) 13 | 14 | suspend fun deleteChecklist(checklist: Checklist) 15 | 16 | suspend fun disableChecklistContent(checklistContent: Content) 17 | 18 | suspend fun persistChecklistContent(checklistContent: Content) 19 | 20 | suspend fun persistChecklist(checklist: Checklist) 21 | 22 | suspend fun fetchAllChecklistFavorite(): List 23 | 24 | suspend fun fetchChecklistCount(): Long 25 | 26 | suspend fun fetchAllChecklist(): List 27 | 28 | suspend fun fetchSubjectById(subjectId: String): Subject? 29 | 30 | suspend fun fetchDifficultyById(difficultyId: String): Difficulty? 31 | 32 | suspend fun fetchAllChecklistInProgress(): List 33 | 34 | suspend fun fetchAllCustomChecklistInProgress(): List 35 | 36 | suspend fun fetchChecklist(checklistId: String): Checklist? 37 | 38 | suspend fun fetchModule(moduleName: String): Module? 39 | 40 | suspend fun fetchPathways(): List 41 | 42 | suspend fun fetchFavoritePathways(): List 43 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/checklist/presenter/ChecklistBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.checklist.presenter 2 | 3 | import org.secfirst.umbrella.data.database.checklist.Checklist 4 | import org.secfirst.umbrella.data.database.checklist.Content 5 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 6 | import org.secfirst.umbrella.feature.checklist.interactor.ChecklistBaseInteractor 7 | import org.secfirst.umbrella.feature.checklist.view.ChecklistView 8 | 9 | interface ChecklistBasePresenter : BasePresenter { 10 | 11 | fun submitChecklistById(uriString: String) 12 | 13 | fun submitInsertChecklistContent(checklistContent: Content) 14 | 15 | fun submitUpdateChecklist(checklist: Checklist) 16 | 17 | fun submitDeleteChecklistContent(checklistContent: Content) 18 | 19 | fun submitDisableChecklistContent(checklistContent: Content) 20 | 21 | fun submitLoadDashboard() 22 | 23 | fun submitInsertCustomChecklist(checklistTitle: String, checklistId: String, checklistValue: List) 24 | 25 | fun submitLoadCustomDashboard() 26 | 27 | fun submitDeleteChecklist(checklist: Checklist) 28 | 29 | fun submitChecklist(checklistId: String) 30 | 31 | fun submitLoadPathways() 32 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/checklist/view/ChecklistView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.checklist.view 2 | 3 | import org.secfirst.umbrella.data.database.checklist.Checklist 4 | import org.secfirst.umbrella.data.database.checklist.Dashboard 5 | import org.secfirst.umbrella.feature.base.view.BaseView 6 | 7 | interface ChecklistView : BaseView { 8 | 9 | fun showDashboard(dashboards: MutableList) {} 10 | 11 | fun getChecklist(checklist: Checklist) {} 12 | 13 | fun showPathways(dashboards: MutableList) {} 14 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/checklist/view/adapter/HostChecklistAdapter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.checklist.view.adapter 2 | 3 | import com.bluelinelabs.conductor.Controller 4 | import com.bluelinelabs.conductor.Router 5 | import com.bluelinelabs.conductor.RouterTransaction 6 | import com.bluelinelabs.conductor.support.RouterPagerAdapter 7 | import org.secfirst.umbrella.R 8 | import org.secfirst.umbrella.feature.checklist.view.controller.DashboardController 9 | 10 | class HostChecklistAdapter(private val host: Controller) : RouterPagerAdapter(host) { 11 | 12 | override fun configureRouter(router: Router, position: Int) { 13 | if (!router.hasRootController()) { 14 | when (position) { 15 | 0 -> router.setRoot(RouterTransaction.with(DashboardController(false))) 16 | 1 -> router.setRoot(RouterTransaction.with(DashboardController(true))) 17 | } 18 | } 19 | } 20 | 21 | override fun getPageTitle(position: Int) = if (position == 0) host.activity?.getString(R.string.checklist_title_tab) 22 | else host.activity?.getString(R.string.custom_checklist_title_tab) 23 | 24 | override fun getCount() = 2 25 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/content/ContentModule.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.content 2 | 3 | import dagger.Module 4 | import dagger.Provides 5 | import org.secfirst.umbrella.feature.content.interactor.ContentBaseInteractor 6 | import org.secfirst.umbrella.feature.content.interactor.ContentInteractorImp 7 | import org.secfirst.umbrella.feature.content.presenter.ContentBasePresenter 8 | import org.secfirst.umbrella.feature.content.presenter.ContentPresenterImp 9 | 10 | 11 | @Module 12 | class ContentModule { 13 | 14 | @Provides 15 | internal fun provideContentInteractor(interactor: ContentInteractorImp): ContentBaseInteractor = interactor 16 | 17 | @Provides 18 | internal fun provideContentPresenter(presenter: ContentPresenterImp) 19 | : ContentBasePresenter = presenter 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/content/ContentView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.content 2 | 3 | import org.secfirst.umbrella.feature.base.view.BaseView 4 | 5 | 6 | interface ContentView : BaseView { 7 | 8 | fun downloadContentCompleted(res: Boolean){} 9 | 10 | fun downloadContentInProgress() {} 11 | 12 | fun onCleanDatabaseSuccess() {} 13 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/content/presenter/ContentBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.content.presenter 2 | 3 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 4 | import org.secfirst.umbrella.feature.content.ContentView 5 | import org.secfirst.umbrella.feature.content.interactor.ContentBaseInteractor 6 | import java.io.File 7 | 8 | 9 | interface ContentBasePresenter : BasePresenter { 10 | 11 | fun manageContent(url:String) 12 | 13 | fun updateContent(pairFiles: List>) 14 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/difficulty/interactor/DifficultyBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.difficulty.interactor 2 | 3 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 4 | import org.secfirst.umbrella.data.database.difficulty.DifficultyPreferred 5 | import org.secfirst.umbrella.data.database.lesson.Subject 6 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 7 | 8 | interface DifficultyBaseInteractor : BaseInteractor { 9 | 10 | suspend fun insertTopicPreferred(difficultyPreferred: DifficultyPreferred) 11 | 12 | suspend fun fetchSubjectBy(subjectSha1ID: String): Subject? 13 | 14 | suspend fun fetchSubjectByModule(moduleSha1ID: String): Subject? 15 | 16 | suspend fun fetchDifficultyBy(sha1ID : String): Difficulty? 17 | 18 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/difficulty/interactor/DifficultyInteractorImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.difficulty.interactor 2 | 3 | import org.secfirst.umbrella.data.database.difficulty.DifficultyPreferred 4 | import org.secfirst.umbrella.data.database.difficulty.DifficultyRepo 5 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractorImp 6 | import javax.inject.Inject 7 | 8 | class DifficultyInteractorImp @Inject constructor(private val difficultyRepo: DifficultyRepo) : BaseInteractorImp(), DifficultyBaseInteractor { 9 | 10 | 11 | override suspend fun fetchSubjectByModule(moduleSha1ID : String) = difficultyRepo.loadSubjectByModule(moduleSha1ID) 12 | 13 | override suspend fun fetchDifficultyBy(sha1ID : String) = difficultyRepo.loadDifficultyBy(sha1ID ) 14 | 15 | override suspend fun insertTopicPreferred(difficultyPreferred: DifficultyPreferred) = difficultyRepo.saveTopicPreferred(difficultyPreferred) 16 | 17 | override suspend fun fetchSubjectBy(subjectSha1ID : String) = difficultyRepo.loadSubjectBy(subjectSha1ID) 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/difficulty/presenter/DifficultyBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.difficulty.presenter 2 | 3 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 4 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 5 | import org.secfirst.umbrella.feature.difficulty.interactor.DifficultyBaseInteractor 6 | import org.secfirst.umbrella.feature.difficulty.view.DifficultyView 7 | 8 | interface DifficultyBasePresenter : BasePresenter { 9 | 10 | fun submitDifficulty(subjectId: String) 11 | 12 | fun saveDifficultySelect(difficulty: Difficulty, subjectId: String) 13 | 14 | fun submitDifficultySelect(difficulties: List) 15 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/difficulty/view/DifficultyView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.difficulty.view 2 | 3 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 4 | import org.secfirst.umbrella.feature.base.view.BaseView 5 | 6 | interface DifficultyView : BaseView { 7 | 8 | fun showDifficulties(difficulties: List, toolbarTitle: String) 9 | 10 | fun startSegment(difficultyIds: List) 11 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/form/FieldType.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.form 2 | 3 | import org.secfirst.umbrella.data.database.form.Answer 4 | import org.secfirst.umbrella.data.database.form.Item 5 | import org.secfirst.umbrella.data.database.form.Option 6 | 7 | enum class FieldType(val value: String) { 8 | TEXT_INPUT("text_input"), 9 | LABEL("label"), 10 | TEXT_AREA("text_area"), 11 | MULTIPLE_CHOICE("multiple_choice"), 12 | SINGLE_CHOICE("single_choice"), 13 | HINT("hint") 14 | } 15 | 16 | fun Option.hasAnswer(answers: List?): Answer { 17 | answers?.forEach { answer -> 18 | if (this.id == answer.optionId) 19 | return answer 20 | } 21 | return Answer() 22 | } 23 | 24 | fun Item.hasAnswer(answers: List?): Answer { 25 | answers?.forEach { answer -> 26 | if (this.id == answer.itemId) 27 | return answer 28 | } 29 | return Answer() 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/form/interactor/FormBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.form.interactor 2 | 3 | import org.secfirst.umbrella.data.database.form.ActiveForm 4 | import org.secfirst.umbrella.data.database.form.Answer 5 | import org.secfirst.umbrella.data.database.form.Form 6 | import org.secfirst.umbrella.data.database.form.Screen 7 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 8 | 9 | 10 | interface FormBaseInteractor : BaseInteractor { 11 | 12 | suspend fun insertFormData(answer: Answer) 13 | 14 | suspend fun insertActiveForm(activeForm: ActiveForm): Boolean 15 | 16 | suspend fun deleteActiveForm(activeForm: ActiveForm) 17 | 18 | suspend fun fetchModalForms(): List 19 | 20 | suspend fun fetchActiveForms(): List 21 | 22 | suspend fun fetchAnswerBy(formId: Long): List 23 | 24 | suspend fun fetchScreenBy(sh1ID: String): List 25 | 26 | suspend fun fetchForm(formTitle: String): Form? 27 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/form/interactor/FormInteractorImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.form.interactor 2 | 3 | import org.secfirst.umbrella.data.database.form.ActiveForm 4 | import org.secfirst.umbrella.data.database.form.Answer 5 | import org.secfirst.umbrella.data.database.form.FormRepo 6 | import org.secfirst.umbrella.data.database.form.Screen 7 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractorImp 8 | import javax.inject.Inject 9 | 10 | class FormInteractorImp @Inject constructor(private val formRepo: FormRepo) : BaseInteractorImp(), FormBaseInteractor { 11 | 12 | override suspend fun fetchForm(formTitle: String) = formRepo.loadForm(formTitle) 13 | 14 | override suspend fun deleteActiveForm(activeForm: ActiveForm) = formRepo.removeActiveForm(activeForm) 15 | 16 | override suspend fun fetchAnswerBy(formId: Long): List = formRepo.loadAnswerBy(formId) 17 | 18 | override suspend fun fetchScreenBy(sh1ID: String): List = formRepo.loadScreenBy(sh1ID) 19 | 20 | override suspend fun insertActiveForm(activeForm: ActiveForm) = formRepo.persistActiveForm(activeForm) 21 | 22 | override suspend fun fetchActiveForms(): List = formRepo.loadActiveForms() 23 | 24 | override suspend fun insertFormData(answer: Answer) = formRepo.persistFormData(answer) 25 | 26 | override suspend fun fetchModalForms() = formRepo.loadModelForms() 27 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/form/presenter/FormBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.form.presenter 2 | 3 | import org.secfirst.umbrella.data.database.form.ActiveForm 4 | import org.secfirst.umbrella.data.database.form.Answer 5 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 6 | import org.secfirst.umbrella.feature.form.interactor.FormBaseInteractor 7 | import org.secfirst.umbrella.feature.form.view.FormView 8 | 9 | interface FormBasePresenter : BasePresenter { 10 | 11 | fun submitLoadAllForms() 12 | 13 | fun submitInsert(answer: Answer) 14 | 15 | fun submitActiveForm(activeForm: ActiveForm) 16 | 17 | fun submitDeleteActiveForm(activeForm: ActiveForm) 18 | 19 | fun submitShareFormHtml(activeForm: ActiveForm) 20 | 21 | fun submitFormByURI(uriString: String) 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/form/view/FormView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.form.view 2 | 3 | import org.secfirst.umbrella.data.database.form.ActiveForm 4 | import org.secfirst.umbrella.data.database.form.Form 5 | import org.secfirst.umbrella.feature.base.view.BaseView 6 | import java.io.File 7 | 8 | interface FormView : BaseView { 9 | 10 | fun showModelAndActiveForms(modelForms: MutableList, activeForms: MutableList) {} 11 | 12 | fun showShareForm(shareFile: File) {} 13 | 14 | fun showActiveFormWLoad(result: Boolean){} 15 | 16 | fun openSpecificForm(form: Form) {} 17 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/lesson/LessonModule.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.lesson 2 | 3 | import android.app.Application 4 | import dagger.BindsInstance 5 | import dagger.Component 6 | import dagger.Module 7 | import dagger.Provides 8 | import dagger.android.AndroidInjectionModule 9 | import org.secfirst.umbrella.di.module.AppModule 10 | import org.secfirst.umbrella.di.module.RepositoryModule 11 | import org.secfirst.umbrella.feature.lesson.interactor.LessonBaseInteractor 12 | import org.secfirst.umbrella.feature.lesson.interactor.LessonInteractorImp 13 | import org.secfirst.umbrella.feature.lesson.presenter.LessonBasePresenter 14 | import org.secfirst.umbrella.feature.lesson.presenter.LessonPresenterImp 15 | import org.secfirst.umbrella.feature.lesson.view.LessonView 16 | import org.secfirst.umbrella.feature.lesson.view.LessonController 17 | import javax.inject.Singleton 18 | 19 | @Module 20 | class LessonModule { 21 | 22 | @Provides 23 | internal fun provideLessonInteractor(interactor: LessonInteractorImp): LessonBaseInteractor = interactor 24 | 25 | @Provides 26 | internal fun provideLessonPresenter(presenter: LessonPresenterImp) 27 | : LessonBasePresenter = presenter 28 | } 29 | 30 | @Singleton 31 | @Component(modules = [LessonModule::class, 32 | RepositoryModule::class, 33 | AppModule::class, 34 | AndroidInjectionModule::class]) 35 | interface LessonComponent { 36 | @Component.Builder 37 | interface Builder { 38 | 39 | @BindsInstance 40 | fun application(application: Application): Builder 41 | 42 | fun build(): LessonComponent 43 | } 44 | 45 | fun inject(lessonController: LessonController) 46 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/lesson/interactor/LessonBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.lesson.interactor 2 | 3 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 4 | import org.secfirst.umbrella.data.database.difficulty.DifficultyPreferred 5 | import org.secfirst.umbrella.data.database.lesson.Module 6 | import org.secfirst.umbrella.data.database.segment.Markdown 7 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 8 | 9 | interface LessonBaseInteractor : BaseInteractor { 10 | 11 | suspend fun fetchModules(): List 12 | 13 | suspend fun fetchLesson(moduleId: String): Module? 14 | 15 | suspend fun fetchMarkdownBySubject(subjectId: String): List 16 | 17 | suspend fun fetchDifficultyBySubject(subjectId: String): List 18 | 19 | suspend fun fetchDifficultyPreferredBy(subjectId: String): DifficultyPreferred? 20 | 21 | suspend fun fetchAllFavorites(): List 22 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/lesson/interactor/LessonInteractorImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.lesson.interactor 2 | 3 | import org.secfirst.umbrella.data.database.lesson.LessonRepo 4 | import org.secfirst.umbrella.data.database.lesson.Module 5 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractorImp 6 | import javax.inject.Inject 7 | 8 | class LessonInteractorImp @Inject constructor(private val lessonRepo: LessonRepo) : BaseInteractorImp(), LessonBaseInteractor { 9 | 10 | override suspend fun fetchDifficultyBySubject(subjectId: String) = lessonRepo.loadDifficultyBySubject(subjectId) 11 | 12 | override suspend fun fetchAllFavorites() = lessonRepo.loadAllFavoriteSubjects() 13 | 14 | override suspend fun fetchMarkdownBySubject(subjectId: String) = lessonRepo.loadMarkdownBySubject(subjectId) 15 | 16 | override suspend fun fetchLesson(moduleId: String) = lessonRepo.loadLessonBy(moduleId) 17 | 18 | override suspend fun fetchDifficultyPreferredBy(subjectId: String) = lessonRepo.loadDifficultyPreferredBy(subjectId) 19 | 20 | override suspend fun fetchModules(): List = lessonRepo.loadAllModules() 21 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/lesson/presenter/LessonBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.lesson.presenter 2 | 3 | import org.secfirst.umbrella.data.database.lesson.Lesson 4 | import org.secfirst.umbrella.data.database.lesson.Subject 5 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 6 | import org.secfirst.umbrella.feature.lesson.interactor.LessonBaseInteractor 7 | import org.secfirst.umbrella.feature.lesson.view.LessonView 8 | 9 | 10 | interface LessonBasePresenter : BasePresenter { 11 | 12 | fun submitLoadAllLesson() 13 | 14 | fun submitSelectLesson(subject: Subject) 15 | 16 | fun submitSelectHead(lesson: Lesson) 17 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/lesson/view/LessonDecorator.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.lesson.view 2 | 3 | import com.xwray.groupie.kotlinandroidextensions.Item 4 | import com.xwray.groupie.kotlinandroidextensions.ViewHolder 5 | import org.secfirst.umbrella.R 6 | 7 | class LessonDecorator : Item() { 8 | 9 | override fun bind(viewHolder: ViewHolder, position: Int) {} 10 | override fun getLayout() = R.layout.lesson_decorator_line 11 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/lesson/view/LessonItem.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.lesson.view 2 | 3 | import com.xwray.groupie.kotlinandroidextensions.Item 4 | import com.xwray.groupie.kotlinandroidextensions.ViewHolder 5 | import kotlinx.android.synthetic.main.lesson_menu_item.* 6 | import org.secfirst.umbrella.R 7 | import org.secfirst.umbrella.data.database.lesson.Subject 8 | 9 | class LessonItem(private val subject: Subject, private val onclickLesson: (Subject) -> Unit) : Item() { 10 | 11 | override fun bind(viewHolder: ViewHolder, position: Int) { 12 | viewHolder.categoryName.text = subject.title 13 | viewHolder.lessonItemLayout.setOnClickListener { onclickLesson(subject) } 14 | } 15 | 16 | override fun getLayout() = R.layout.lesson_menu_item 17 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/lesson/view/LessonView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.lesson.view 2 | 3 | 4 | import org.secfirst.umbrella.data.database.lesson.Lesson 5 | import org.secfirst.umbrella.data.database.lesson.Subject 6 | import org.secfirst.umbrella.data.database.segment.Markdown 7 | import org.secfirst.umbrella.feature.base.view.BaseView 8 | 9 | interface LessonView : BaseView { 10 | 11 | fun showAllLesson(lessons: List) 12 | 13 | fun startDifficultyController(subject: Subject) 14 | 15 | fun startSegment(markdownIds: ArrayList, enableFilter: Boolean) 16 | 17 | fun startSegmentAlone(markdown: Markdown) 18 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/login/interactor/LoginBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.login.interactor 2 | 3 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 4 | 5 | interface LoginBaseInteractor : BaseInteractor { 6 | 7 | suspend fun changeDatabaseAccess(userToken: String): Boolean 8 | 9 | fun dispatchLoginDatabaseAccess(userToken: String) 10 | 11 | fun dispatchDatabaseIntegrity(): Boolean 12 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/login/interactor/LoginInteractorImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.login.interactor 2 | 3 | import org.secfirst.umbrella.data.database.content.ContentRepo 4 | import org.secfirst.umbrella.data.database.login.LoginRepo 5 | import org.secfirst.umbrella.data.network.ApiHelper 6 | import org.secfirst.umbrella.data.preferences.AppPreferenceHelper 7 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractorImp 8 | import javax.inject.Inject 9 | 10 | class LoginInteractorImp @Inject constructor(private val loginRepo: LoginRepo, 11 | apiHelper: ApiHelper, 12 | preferenceHelper: AppPreferenceHelper, 13 | contentRepo: ContentRepo) : BaseInteractorImp(apiHelper, preferenceHelper, contentRepo), LoginBaseInteractor { 14 | 15 | 16 | override fun dispatchDatabaseIntegrity() = loginRepo.verifyDatabaseIntegrity() 17 | 18 | override fun dispatchLoginDatabaseAccess(userToken: String) = loginRepo.loginDatabase(userToken) 19 | 20 | override suspend fun changeDatabaseAccess(userToken: String) = loginRepo.changeToken(userToken) 21 | 22 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/login/presenter/LoginBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.login.presenter 2 | 3 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 4 | import org.secfirst.umbrella.feature.login.interactor.LoginBaseInteractor 5 | import org.secfirst.umbrella.feature.login.view.LoginView 6 | 7 | 8 | interface LoginBasePresenter : BasePresenter { 9 | 10 | fun submitChangeDatabaseAccess(userToken: String) 11 | 12 | fun submitResetPassword() 13 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/login/presenter/LoginPresenterImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.login.presenter 2 | 3 | import org.secfirst.umbrella.UmbrellaApplication 4 | import org.secfirst.umbrella.feature.base.presenter.BasePresenterImp 5 | import org.secfirst.umbrella.feature.login.interactor.LoginBaseInteractor 6 | import org.secfirst.umbrella.feature.login.view.LoginView 7 | import org.secfirst.umbrella.misc.AppExecutors.Companion.uiContext 8 | import org.secfirst.umbrella.misc.launchSilent 9 | import javax.inject.Inject 10 | 11 | 12 | class LoginPresenterImp @Inject constructor( 13 | interactor: I) : BasePresenterImp( 14 | interactor = interactor), LoginBasePresenter { 15 | 16 | override fun submitResetPassword() { 17 | launchSilent(uiContext) { 18 | interactor?.let { 19 | val res = it.resetContent() 20 | getView()?.onResetContent(res) 21 | } 22 | } 23 | } 24 | 25 | override fun submitChangeDatabaseAccess(userToken: String) { 26 | interactor?.let { 27 | launchSilent(uiContext) { 28 | if (UmbrellaApplication.instance.checkPassword(userToken)) { 29 | it.dispatchLoginDatabaseAccess(userToken) 30 | it.setSkipPassword(true) 31 | getView()?.isLoginOk(true) 32 | } else { 33 | getView()?.isLoginOk(false) 34 | } 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/login/view/LoginView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.login.view 2 | 3 | import org.secfirst.umbrella.feature.base.view.BaseView 4 | 5 | interface LoginView : BaseView { 6 | 7 | fun isLoginOk(isLogged: Boolean) 8 | fun onResetContent(res: Boolean) 9 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/maskapp/interactor/MaskAppBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.maskapp.interactor 2 | 3 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 4 | 5 | 6 | interface MaskAppBaseInteractor : BaseInteractor { 7 | 8 | fun setMaskApp(res : Boolean) : Boolean 9 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/maskapp/interactor/MaskAppInteractorImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.maskapp.interactor 2 | 3 | import org.secfirst.umbrella.data.database.content.ContentRepo 4 | import org.secfirst.umbrella.data.network.ApiHelper 5 | import org.secfirst.umbrella.data.preferences.AppPreferenceHelper 6 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractorImp 7 | import javax.inject.Inject 8 | 9 | class MaskAppInteractorImp @Inject constructor(apiHelper: ApiHelper, preferenceHelper: AppPreferenceHelper, contentRepo: ContentRepo) 10 | : BaseInteractorImp(apiHelper, preferenceHelper, contentRepo), MaskAppBaseInteractor { 11 | 12 | override fun setMaskApp(res: Boolean) = preferenceHelper.setMaskApp(res) 13 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/maskapp/presenter/MaskAppBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.maskapp.presenter 2 | 3 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 4 | import org.secfirst.umbrella.feature.maskapp.interactor.MaskAppBaseInteractor 5 | import org.secfirst.umbrella.feature.maskapp.view.MaskAppView 6 | 7 | 8 | interface MaskAppBasePresenter : BasePresenter { 9 | 10 | fun setMaskApp() 11 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/maskapp/presenter/MaskAppPresenterImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.maskapp.presenter 2 | 3 | import org.secfirst.umbrella.feature.base.presenter.BasePresenterImp 4 | import org.secfirst.umbrella.feature.maskapp.interactor.MaskAppBaseInteractor 5 | import org.secfirst.umbrella.feature.maskapp.view.MaskAppView 6 | import javax.inject.Inject 7 | 8 | 9 | class MaskAppPresenterImp @Inject constructor( 10 | interactor: I) : BasePresenterImp( 11 | interactor = interactor), MaskAppBasePresenter { 12 | 13 | override fun setMaskApp() { 14 | val res = interactor?.setMaskApp(false) ?: false 15 | getView()?.isMaskApp(res) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/maskapp/view/MaskAppView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.maskapp.view 2 | 3 | import org.secfirst.umbrella.feature.base.view.BaseView 4 | 5 | interface MaskAppView : BaseView { 6 | 7 | fun isMaskApp(res: Boolean) 8 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/reader/interactor/ReaderBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.reader.interactor 2 | 3 | 4 | import kotlinx.coroutines.Deferred 5 | import okhttp3.ResponseBody 6 | import org.secfirst.umbrella.data.database.reader.FeedLocation 7 | import org.secfirst.umbrella.data.database.reader.FeedSource 8 | import org.secfirst.umbrella.data.database.reader.RSS 9 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 10 | 11 | interface ReaderBaseInteractor : BaseInteractor { 12 | 13 | suspend fun insertRss(rss: RSS) 14 | 15 | suspend fun insertFeedLocation(feedLocation: FeedLocation) 16 | 17 | suspend fun insertAllFeedSources(feedSources: List) 18 | 19 | suspend fun insertAllRss(rssList: List) 20 | 21 | suspend fun fetchRss(): List 22 | 23 | suspend fun fetchFeedSources(): List 24 | 25 | suspend fun fetchFeedLocation(): FeedLocation? 26 | 27 | suspend fun deleteRss(rss: RSS): Boolean 28 | 29 | suspend fun deleteLocation() 30 | 31 | suspend fun doRSsCallAsync(url: String): Deferred 32 | 33 | suspend fun fetchRefreshInterval(): Int 34 | 35 | suspend fun putRefreshInterval(position: Int): Boolean 36 | 37 | suspend fun doFeedCallAsync(countryCode: String, source: String, since: String): Deferred 38 | 39 | suspend fun applyChangeDatabaseAccess(userToken: String): Boolean 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/reader/presenter/ReaderBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.reader.presenter 2 | 3 | import org.secfirst.umbrella.data.database.reader.FeedLocation 4 | import org.secfirst.umbrella.data.database.reader.FeedSource 5 | import org.secfirst.umbrella.data.database.reader.RSS 6 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 7 | import org.secfirst.umbrella.feature.reader.interactor.ReaderBaseInteractor 8 | import org.secfirst.umbrella.feature.reader.view.ReaderView 9 | 10 | interface ReaderBasePresenter : BasePresenter { 11 | 12 | fun submitFetchRss() 13 | 14 | fun submitInsertRss(rss: RSS) 15 | 16 | fun submitDeleteRss(rss: RSS) 17 | 18 | fun submitDeleteFeedLocation() 19 | 20 | fun submitInsertFeedSource(feedSources: List) 21 | 22 | fun submitFeedRequest(feedLocation: FeedLocation, 23 | feedSources: List, 24 | isFirstRequest: Boolean = false) 25 | 26 | fun submitFeedLocation(feedLocation: FeedLocation) 27 | 28 | fun submitInsertFeedLocation(feedLocation: FeedLocation) 29 | 30 | fun submitPutRefreshInterval(position: Int) 31 | 32 | fun prepareView() 33 | 34 | fun isSkipPassword() 35 | 36 | fun setSkipPassword(value : Boolean) 37 | 38 | fun submitChangeDatabaseAccess(userToken: String) 39 | 40 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/reader/view/HostReaderController.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.reader.view 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import kotlinx.android.synthetic.main.host_reader_view.* 8 | import kotlinx.android.synthetic.main.host_reader_view.view.* 9 | import org.secfirst.umbrella.R 10 | import org.secfirst.umbrella.feature.base.view.BaseController 11 | 12 | 13 | class HostReaderController : BaseController() { 14 | 15 | override fun onInject() { 16 | } 17 | 18 | override fun onAttach(view: View) { 19 | enableNavigation(true) 20 | feedPager?.adapter = ReaderAdapter(this) 21 | feedTab?.setupWithViewPager(feedPager) 22 | } 23 | 24 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle?): View { 25 | val view = inflater.inflate(R.layout.host_reader_view, container, false) 26 | view.toolbar.let { 27 | mainActivity.setSupportActionBar(it) 28 | mainActivity.supportActionBar?.title = context.getString(R.string.feed_title) 29 | } 30 | return view 31 | } 32 | 33 | override fun onDestroyView(view: View) { 34 | feedPager?.adapter = null 35 | feedTab?.setupWithViewPager(null) 36 | super.onDestroyView(view) 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/reader/view/ReaderAdapter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.reader.view 2 | 3 | import com.bluelinelabs.conductor.Controller 4 | import com.bluelinelabs.conductor.Router 5 | import com.bluelinelabs.conductor.RouterTransaction 6 | import com.bluelinelabs.conductor.support.RouterPagerAdapter 7 | import org.secfirst.umbrella.R 8 | import org.secfirst.umbrella.feature.reader.view.feed.FeedSettingsController 9 | import org.secfirst.umbrella.feature.reader.view.rss.RssController 10 | 11 | class ReaderAdapter(private val host: Controller) : RouterPagerAdapter(host) { 12 | override fun configureRouter(router: Router, position: Int) { 13 | if (!router.hasRootController()) { 14 | when (position) { 15 | 0 -> router.setRoot(RouterTransaction.with(FeedSettingsController())) 16 | 1 -> router.setRoot(RouterTransaction.with(RssController())) 17 | } 18 | } 19 | } 20 | 21 | override fun getPageTitle(position: Int): String { 22 | return when (position) { 23 | 0 -> host.applicationContext?.getString(R.string.feed_title_tab) ?: "" 24 | 1 -> host.applicationContext?.getString(R.string.rss_title_tab) ?: "" 25 | else -> "" 26 | } 27 | } 28 | 29 | override fun getCount() = 2 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/reader/view/ReaderView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.reader.view 2 | 3 | import org.secfirst.umbrella.data.database.reader.FeedLocation 4 | import org.secfirst.umbrella.data.database.reader.FeedSource 5 | import org.secfirst.umbrella.data.database.reader.RSS 6 | import org.secfirst.umbrella.data.network.FeedItemResponse 7 | import org.secfirst.umbrella.feature.base.view.BaseView 8 | 9 | interface ReaderView : BaseView { 10 | 11 | fun showRss(rss: RSS) {} 12 | 13 | fun showNewestRss(rss: RSS) {} 14 | 15 | fun showRssError() {} 16 | 17 | fun isSkipPassword(res: Boolean) {} 18 | 19 | fun isChangedToken(res: Boolean) {} 20 | 21 | fun startFeedController(feedItemResponse: Array, isFirstRequest: Boolean = false) {} 22 | 23 | fun feedError() {} 24 | 25 | fun prepareView(feedSources: List, 26 | refreshInterval: String, 27 | feedLocation: FeedLocation) { 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/search/SearchModule.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.search 2 | 3 | import android.app.Application 4 | import dagger.BindsInstance 5 | import dagger.Component 6 | import dagger.Module 7 | import dagger.Provides 8 | import dagger.android.AndroidInjectionModule 9 | import org.secfirst.umbrella.feature.search.interactor.SearchBaseInteractor 10 | import org.secfirst.umbrella.feature.search.interactor.SearchInteractorImp 11 | import org.secfirst.umbrella.feature.search.presenter.SearchBasePresenter 12 | import org.secfirst.umbrella.feature.search.presenter.SearchPresenterImp 13 | import org.secfirst.umbrella.feature.search.view.SearchController 14 | import org.secfirst.umbrella.feature.search.view.SearchView 15 | import javax.inject.Singleton 16 | 17 | @Module 18 | class SearchModule { 19 | 20 | @Provides 21 | internal fun provideSearchInteractor(interactor: SearchInteractorImp): SearchBaseInteractor = interactor 22 | 23 | @Provides 24 | internal fun provideSearchPresenter(presenter: SearchPresenterImp) 25 | : SearchBasePresenter = presenter 26 | } 27 | 28 | @Singleton 29 | @Component(modules = [ 30 | SearchModule::class, 31 | AndroidInjectionModule::class 32 | ]) 33 | interface SearchComponent { 34 | @Component.Builder 35 | interface Builder { 36 | 37 | @BindsInstance 38 | fun application(application: Application): Builder 39 | 40 | fun build(): SearchComponent 41 | } 42 | 43 | fun inject(searchController: SearchController) 44 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/search/interactor/SearchBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.search.interactor 2 | 3 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 4 | 5 | interface SearchBaseInteractor:BaseInteractor { 6 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/search/interactor/SearchInteractorImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.search.interactor 2 | 3 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractorImp 4 | import javax.inject.Inject 5 | 6 | class SearchInteractorImp @Inject constructor() : BaseInteractorImp(), SearchBaseInteractor { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/search/presenter/SearchBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.search.presenter 2 | 3 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 4 | import org.secfirst.umbrella.feature.search.interactor.SearchBaseInteractor 5 | import org.secfirst.umbrella.feature.search.view.SearchView 6 | 7 | interface SearchBasePresenter : BasePresenter { 8 | 9 | fun submitSearchQuery(query: String) 10 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/search/view/SearchView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.search.view 2 | 3 | import org.secfirst.umbrella.feature.base.view.BaseView 4 | 5 | interface SearchView : BaseView { 6 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/segment/SegmentPagination.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.segment 2 | 3 | import org.secfirst.umbrella.data.database.segment.Markdown 4 | import org.secfirst.umbrella.data.database.segment.sortByIndex 5 | import org.secfirst.umbrella.data.disk.Template 6 | 7 | class SegmentPagination(private val markdowns: MutableList) { 8 | 9 | private val limitPage = 6 10 | 11 | fun nextPage(): List { 12 | var glossary = false 13 | val pages = mutableListOf() 14 | markdowns.forEach { 15 | if (it.id.contains(Template.GLOSSARY.value)) { 16 | glossary = true 17 | } 18 | } 19 | 20 | if (markdowns.size <= limitPage) { 21 | pages.addAll(markdowns) 22 | markdowns.clear() 23 | } else { 24 | if (markdowns.isNotEmpty()) { 25 | (0..limitPage).forEach { pages.add(markdowns[it]) } 26 | (0..limitPage).forEach { _ -> markdowns .removeAt(0) } 27 | } 28 | } 29 | if (glossary){ 30 | return pages 31 | } 32 | 33 | return pages.sortByIndex() 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/segment/interactor/SegmentBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.segment.interactor 2 | 3 | import org.secfirst.umbrella.data.database.checklist.Checklist 4 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 5 | import org.secfirst.umbrella.data.database.lesson.Module 6 | import org.secfirst.umbrella.data.database.lesson.Subject 7 | import org.secfirst.umbrella.data.database.segment.Markdown 8 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 9 | 10 | interface SegmentBaseInteractor : BaseInteractor { 11 | 12 | suspend fun fetchMarkdown(markdownId: String): Markdown? 13 | 14 | suspend fun fetchChecklist(checklistId: String): Checklist? 15 | 16 | suspend fun fetchSubject(subjectId: String): Subject? 17 | 18 | suspend fun fetchModule(moduleId: String): Module? 19 | 20 | suspend fun fetchModuleByRootDir(rootDir: String): Module? 21 | 22 | suspend fun fetchDifficulty(difficultyId: String): Difficulty? 23 | 24 | suspend fun fetchSubjectByRootDir(rootDir: String): Subject? 25 | 26 | suspend fun fetchDifficultyBySubject(subjectId: String): List 27 | 28 | suspend fun insertChecklist(checklist: Checklist) 29 | 30 | suspend fun insertMarkdown(markdown: Markdown) 31 | 32 | suspend fun insertDifficultySelect(subjectId: String, difficulty: Difficulty) 33 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/segment/presenter/SegmentBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.segment.presenter 2 | 3 | import org.secfirst.umbrella.data.database.checklist.Checklist 4 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 5 | import org.secfirst.umbrella.data.database.segment.Markdown 6 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 7 | import org.secfirst.umbrella.feature.segment.interactor.SegmentBaseInteractor 8 | import org.secfirst.umbrella.feature.segment.view.SegmentView 9 | 10 | 11 | interface SegmentBasePresenter : BasePresenter { 12 | 13 | fun submitLoadDifficulties(difficultyIds: ArrayList) 14 | 15 | fun submitChecklistFavorite(checklist: Checklist) 16 | 17 | fun submitMarkdownFavorite(markdown: Markdown) 18 | 19 | fun submitDifficultySelected(subjectId: String, difficulty: Difficulty) 20 | 21 | fun submitMarkdowns(markdownIds: ArrayList) 22 | 23 | fun submitMarkdownsAndChecklist(markdownIds: ArrayList, checklistId: String) 24 | 25 | fun submitDifficulties(difficultyIds: ArrayList) 26 | 27 | fun submitTitleToolbar(subjectId: String = "", moduleId: String = "") 28 | 29 | fun submitMarkdownsByURI(uri: String) 30 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/segment/view/SegmentFoot.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.segment.view 2 | 3 | import androidx.core.content.ContextCompat 4 | import com.xwray.groupie.kotlinandroidextensions.Item 5 | import com.xwray.groupie.kotlinandroidextensions.ViewHolder 6 | import kotlinx.android.synthetic.main.segment_foot.* 7 | import org.jetbrains.anko.backgroundColor 8 | import org.secfirst.umbrella.R 9 | import org.secfirst.umbrella.data.database.checklist.Checklist 10 | import org.secfirst.umbrella.misc.appContext 11 | 12 | 13 | class SegmentFoot(private val onFootClicked: (Int) -> Unit, 14 | private val onChecklistShareClick: () -> Unit, 15 | private val onChecklistFavoriteClick: (Boolean) -> Unit, 16 | private val checklist: Checklist) : Item() { 17 | 18 | override fun bind(viewHolder: ViewHolder, position: Int) { 19 | val colours = intArrayOf(R.color.umbrella_purple, 20 | R.color.umbrella_green, 21 | R.color.umbrella_yellow) 22 | 23 | viewHolder.checklistShare.setOnClickListener { onChecklistShareClick() } 24 | viewHolder.segmentFootLayout.setOnClickListener { onFootClicked(position) } 25 | viewHolder.checklistFavorite.isChecked = checklist.favorite 26 | viewHolder.footLayout.backgroundColor = ContextCompat.getColor(appContext(), colours[position % 3]) 27 | viewHolder.checklistFavorite.setOnClickListener { 28 | onChecklistFavoriteClick(viewHolder.checklistFavorite.isChecked) 29 | } 30 | } 31 | 32 | override fun getLayout() = R.layout.segment_foot 33 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/segment/view/SegmentItem.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.segment.view 2 | 3 | import org.secfirst.umbrella.data.database.segment.Markdown 4 | 5 | open class SegmentItem(onClickSegment: (Int) -> Unit, 6 | onSegmentShareClick: (Markdown) -> Unit, 7 | onSegmentFavoriteClick: (Markdown) -> Unit, 8 | markdown: Markdown?) : SegmentCard(onClickSegment, onSegmentShareClick, onSegmentFavoriteClick, markdown) { 9 | 10 | override fun getSpanSize(spanCount: Int, position: Int) = spanCount / 2 11 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/segment/view/SegmentView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.segment.view 2 | 3 | import org.secfirst.umbrella.data.database.checklist.Checklist 4 | import org.secfirst.umbrella.data.database.difficulty.Difficulty 5 | import org.secfirst.umbrella.data.database.segment.Markdown 6 | import org.secfirst.umbrella.feature.base.view.BaseView 7 | 8 | interface SegmentView : BaseView { 9 | 10 | fun showSegmentDetail(markdown: Markdown) {} 11 | 12 | fun showSegmentsWithDifficulty(difficulties: List, markdownIndexSelected: Int = -1) {} 13 | 14 | fun showSegments(markdowns: List, markdownIndexSelected: Int = -1) {} 15 | 16 | fun showSegments(markdowns: List, checklist: Checklist?) {} 17 | 18 | fun getTitleToolbar(title: String) {} 19 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/segment/view/adapter/GroupAdapter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.segment.view.adapter 2 | 3 | import com.xwray.groupie.Group 4 | import com.xwray.groupie.GroupAdapter 5 | import com.xwray.groupie.kotlinandroidextensions.ViewHolder 6 | 7 | class GroupAdapter : GroupAdapter() { 8 | 9 | private var groupSize = 0 10 | 11 | override fun add(group: Group) { 12 | groupSize += 1 13 | super.add(group) 14 | } 15 | 16 | override fun add(index: Int, group: Group) { 17 | groupSize += 1 18 | super.add(index, group) 19 | } 20 | 21 | fun getGroupSize() = groupSize 22 | 23 | fun lastGroupPosition() = groupSize - 1 24 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/tent/TentModule.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.tent 2 | 3 | import dagger.Module 4 | import dagger.Provides 5 | import org.secfirst.umbrella.feature.tent.interactor.TentBaseInteractor 6 | import org.secfirst.umbrella.feature.tent.interactor.TentInteractorImp 7 | import org.secfirst.umbrella.feature.tent.presenter.TentBasePresenter 8 | import org.secfirst.umbrella.feature.tent.presenter.TentPresenterImp 9 | 10 | @Module 11 | class TentModule{ 12 | 13 | @Provides 14 | internal fun provideTentInteractor(interactor: TentInteractorImp): TentBaseInteractor = interactor 15 | 16 | @Provides 17 | internal fun provideTentPresenter(presenter: TentPresenterImp) 18 | : TentBasePresenter = presenter 19 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/tent/TentView.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.tent 2 | 3 | import org.secfirst.umbrella.feature.base.view.BaseView 4 | import java.io.File 5 | 6 | interface TentView : BaseView { 7 | 8 | fun isUpdateRepository(pairFiles: List>) { 9 | println(pairFiles.forEach { it.second.absolutePath }) 10 | } 11 | 12 | fun isFetchRepository(res: Boolean) {} 13 | 14 | fun onLoadElementSuccess(files: List) {} 15 | 16 | fun getCategoryImage(imagePath: String) {} 17 | 18 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/tent/interactor/TentBaseInteractor.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.tent.interactor 2 | 3 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractor 4 | import java.io.File 5 | 6 | interface TentBaseInteractor : BaseInteractor { 7 | 8 | suspend fun updateRepository(): List> 9 | 10 | suspend fun fetchRepository(url: String): Boolean 11 | 12 | suspend fun loadElementsFile(path : String): List 13 | 14 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/tent/interactor/TentInteractorImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.tent.interactor 2 | 3 | import org.secfirst.umbrella.data.disk.TentRepo 4 | import org.secfirst.umbrella.feature.base.interactor.BaseInteractorImp 5 | import javax.inject.Inject 6 | 7 | class TentInteractorImp @Inject constructor(private val tentRepo: TentRepo) 8 | : BaseInteractorImp(), TentBaseInteractor { 9 | 10 | override suspend fun updateRepository() = tentRepo.updateRepository() 11 | 12 | override suspend fun fetchRepository(url: String) = tentRepo.fetchRepository(url) 13 | 14 | override suspend fun loadElementsFile(path : String) = tentRepo.loadElementsFile(path) 15 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/tent/presenter/TentBasePresenter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.tent.presenter 2 | 3 | import org.secfirst.umbrella.feature.base.presenter.BasePresenter 4 | import org.secfirst.umbrella.feature.tent.TentView 5 | import org.secfirst.umbrella.feature.tent.interactor.TentBaseInteractor 6 | 7 | interface TentBasePresenter : BasePresenter { 8 | 9 | fun submitUpdateRepository() 10 | 11 | fun submitFetchRepository(url : String) 12 | 13 | fun submitLoadElementsFile(path : String) 14 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/tent/presenter/TentPresenterImp.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.tent.presenter 2 | 3 | import org.secfirst.umbrella.feature.base.presenter.BasePresenterImp 4 | import org.secfirst.umbrella.feature.tent.TentView 5 | import org.secfirst.umbrella.feature.tent.interactor.TentBaseInteractor 6 | import org.secfirst.umbrella.misc.AppExecutors.Companion.uiContext 7 | import org.secfirst.umbrella.misc.launchSilent 8 | import javax.inject.Inject 9 | 10 | class TentPresenterImp 11 | @Inject internal constructor( 12 | interactor: I) : BasePresenterImp( 13 | interactor = interactor), TentBasePresenter { 14 | 15 | override fun submitUpdateRepository() { 16 | launchSilent(uiContext) { 17 | interactor?.let { 18 | getView()?.isUpdateRepository(it.updateRepository()) 19 | } 20 | } 21 | } 22 | 23 | override fun submitFetchRepository(url : String) { 24 | launchSilent(uiContext) { 25 | interactor?.let { 26 | getView()?.isFetchRepository(it.fetchRepository(url)) 27 | } 28 | } 29 | } 30 | 31 | override fun submitLoadElementsFile(path : String) { 32 | launchSilent(uiContext) { 33 | interactor?.let { 34 | getView()?.onLoadElementSuccess(it.loadElementsFile(path)) 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/tour/TourModule.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.tour 2 | 3 | import android.app.Application 4 | import dagger.BindsInstance 5 | import dagger.Component 6 | import dagger.android.AndroidInjectionModule 7 | import org.secfirst.umbrella.di.builder.ActivityBuilder 8 | import org.secfirst.umbrella.di.module.AppModule 9 | import org.secfirst.umbrella.di.module.NetworkModule 10 | import org.secfirst.umbrella.di.module.RepositoryModule 11 | import org.secfirst.umbrella.di.module.TentContentModule 12 | import org.secfirst.umbrella.feature.content.ContentModule 13 | import org.secfirst.umbrella.feature.tour.view.TourController 14 | import javax.inject.Singleton 15 | 16 | @Singleton 17 | @Component(modules = [(AndroidInjectionModule::class), 18 | AppModule::class, 19 | RepositoryModule::class, 20 | ContentModule::class, 21 | TentContentModule::class, 22 | NetworkModule::class, 23 | ActivityBuilder::class]) 24 | interface TourComponent { 25 | @Component.Builder 26 | interface Builder { 27 | 28 | @BindsInstance 29 | fun application(application: Application): Builder 30 | 31 | fun build(): TourComponent 32 | } 33 | 34 | fun inject(tourController: TourController) 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/feature/tour/view/TourAdapter.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.feature.tour.view 2 | 3 | import android.view.View 4 | import android.view.ViewGroup 5 | import androidx.viewpager.widget.PagerAdapter 6 | import org.jetbrains.anko.AnkoContext 7 | import org.secfirst.umbrella.UmbrellaApplication 8 | 9 | class TourAdapter(private val controller: TourController) : PagerAdapter() { 10 | 11 | private val childrenViews = mutableListOf() 12 | 13 | override fun isViewFromObject(view: View, `object`: Any): Boolean { 14 | return view === `object` 15 | } 16 | 17 | override fun destroyItem(collection: ViewGroup, position: Int, view: Any) { 18 | collection.removeView(view as View) 19 | } 20 | 21 | override fun instantiateItem(collection: ViewGroup, position: Int): View { 22 | val view = childrenViews[position].createView(AnkoContext.create(UmbrellaApplication.instance, controller, false)) 23 | collection.addView(view) 24 | return view 25 | } 26 | 27 | override fun getItemPosition(`object`: Any): Int { 28 | return PagerAdapter.POSITION_NONE 29 | } 30 | 31 | fun setData(list: List?) { 32 | childrenViews.clear() 33 | if (list != null && !list.isEmpty()) { 34 | childrenViews.addAll(list) 35 | } 36 | 37 | notifyDataSetChanged() 38 | } 39 | 40 | override fun getCount(): Int { 41 | return childrenViews.size 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/misc/AboutController.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.misc 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import br.tiagohm.markdownview.css.styles.Github 8 | import kotlinx.android.synthetic.main.about.* 9 | import org.secfirst.umbrella.R 10 | import org.secfirst.umbrella.data.database.segment.Markdown 11 | import org.secfirst.umbrella.feature.base.view.BaseController 12 | 13 | class AboutController(bundle: Bundle) : BaseController(bundle) { 14 | 15 | private val markdown by lazy { args.getParcelable(EXTRA_ABOUT) as Markdown } 16 | 17 | constructor(markdown: Markdown) : this(Bundle().apply { 18 | putParcelable(EXTRA_ABOUT, markdown) 19 | }) 20 | 21 | companion object { 22 | private const val EXTRA_ABOUT = "extra about" 23 | } 24 | 25 | override fun onInject() { 26 | 27 | } 28 | 29 | override fun onAttach(view: View) { 30 | super.onAttach(view) 31 | aboutMarkdownView.addStyleSheet(Github()) 32 | aboutMarkdownView.loadMarkdown(markdown.text) 33 | setUpToolbar() 34 | } 35 | 36 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle?): View { 37 | return inflater.inflate(R.layout.about, container, false) 38 | } 39 | 40 | private fun setUpToolbar() { 41 | aboutToolbar?.let { 42 | mainActivity.setSupportActionBar(it) 43 | mainActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true) 44 | mainActivity.supportActionBar?.title = markdown.title 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/misc/AppExecutors.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.misc 2 | 3 | import kotlinx.coroutines.Dispatchers 4 | import kotlin.coroutines.CoroutineContext 5 | 6 | /** 7 | * Global executor pools for the whole application. 8 | */ 9 | open class AppExecutors { 10 | companion object { 11 | val ioContext: CoroutineContext 12 | get() = Dispatchers.IO 13 | 14 | val uiContext: CoroutineContext 15 | get() = Dispatchers.Main 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/org/secfirst/umbrella/misc/CoroutineExt.kt: -------------------------------------------------------------------------------- 1 | package org.secfirst.umbrella.misc 2 | 3 | import kotlinx.coroutines.* 4 | import kotlin.coroutines.CoroutineContext 5 | import kotlin.coroutines.EmptyCoroutineContext 6 | 7 | /** 8 | * Equivalent to [launch] but return [Unit] instead of [Job]. 9 | * 10 | * Mainly for usage when you want to lift [launch] to return. Example: 11 | * 12 | * ``` 13 | * override fun loadData() = launchSilent { 14 | * // code 15 | * } 16 | * ``` 17 | */ 18 | fun launchSilent(context: CoroutineContext = Dispatchers.Default, 19 | block: suspend CoroutineScope.() -> Unit) { 20 | 21 | GlobalScope.launch(context, CoroutineStart.DEFAULT, block) 22 | } 23 | 24 | /** 25 | * Equivalent to [launch] but return [Unit] instead of [Job]. 26 | * 27 | * Mainly for usage when you want to lift [launch] to return. Example: 28 | * 29 | * ``` 30 | * override fun loadData() = launchSilent { 31 | * // code 32 | * } 33 | * ``` 34 | */ 35 | fun runBlockingSilent(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T) { 36 | runBlocking(context, block) 37 | } 38 | 39 | //suspend fun async(block: suspend CoroutineScope.() -> T): Deferred { 40 | // return async(CommonPool) { block() } 41 | //} 42 | 43 | //suspend fun asyncAwait(block: suspend CoroutineScope.() -> T): T { 44 | // return async(block).await() 45 | //} -------------------------------------------------------------------------------- /app/src/main/res/animator/opacity_pulse.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 12 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/animator/rotation_collapse_to_expand.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/animator/rotation_expand_to_collapse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/color/nav_item_color_state.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ae.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ae.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/cn.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/dialog_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/es.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/es.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/fr.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/gb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/gb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_account_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_account_box.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_alarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_alarm.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_checklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_checklist.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_form.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_local_library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_local_library.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_person_pin_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_person_pin_circle.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_shake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_shake.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_share_segment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_share_segment.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_star_border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_star_border.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_star_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_star_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_view_feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_view_feed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_walkthrough.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_walkthrough.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_walkthrough1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_walkthrough1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_walkthrough2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_walkthrough2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_walkthrough3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ic_walkthrough3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ir.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/login_umbrella.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/login_umbrella.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/popup_fixed_alert.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/popup_fixed_alert.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ru.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-hdpi/ta.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ae.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/ae.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/es.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/es.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/fr.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/gb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/gb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_star_border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/ic_star_border.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_star_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/ic_star_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_walkthrough1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/ic_walkthrough1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_walkthrough2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/ic_walkthrough2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_walkthrough3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/ic_walkthrough3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/ir.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/ru.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-mdpi/ta.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ae.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ae.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/baseline_search_white_36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/baseline_search_white_36.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/cn.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/es.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/es.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/fr.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/gb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/gb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_account_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_account_box.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_add_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_add_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_alarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_alarm.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_beginner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_beginner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_cast_connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_cast_connected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_checklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_checklist.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_expert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_expert.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_fav.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_fav_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_fav_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_form.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_intermediate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_intermediate.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_local_library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_local_library.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_mode_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_mode_edit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_person_pin_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_person_pin_circle.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_shake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_shake.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_share_segment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_share_segment.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_star_border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_star_border.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_star_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_star_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_view_feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_view_feed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_walkthrough.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_walkthrough.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_walkthrough1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_walkthrough1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_walkthrough2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_walkthrough2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_walkthrough3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ic_walkthrough3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ir.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/login_umbrella.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/login_umbrella.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/popup_fixed_alert.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/popup_fixed_alert.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ru.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xhdpi/ta.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ae.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ae.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/baseline_search_white_36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/baseline_search_white_36.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/cn.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/default_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/default_image.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/es.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/es.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/fr.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/gb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_account_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_account_box.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_add_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_alarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_alarm.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_beginner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_beginner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_cast_connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_cast_connected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_checklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_checklist.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_expert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_expert.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_fav.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_fav_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_fav_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_form.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_intermediate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_intermediate.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_keyboard_arrow_down_black.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_keyboard_arrow_up_black.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_local_library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_local_library.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_mode_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_mode_edit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_person_pin_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_person_pin_circle.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_shake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_shake.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_share_segment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_share_segment.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_star_border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_star_border.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_star_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_star_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_view_feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_view_feed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_walkthrough.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_walkthrough.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_walkthrough1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_walkthrough1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_walkthrough2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_walkthrough2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_walkthrough3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ic_walkthrough3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ir.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/login_umbrella.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/login_umbrella.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ms_right_arrow.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/popup_fixed_alert.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/popup_fixed_alert.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ru.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxhdpi/ta.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ae.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ae.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/baseline_search_white_36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/baseline_search_white_36.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/cn.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/es.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/es.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/fr.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/gb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/gb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_account_box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_account_box.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_add_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_add_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_alarm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_alarm.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_beginner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_beginner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_cast_connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_cast_connected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_checklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_checklist.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_expert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_expert.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_fav.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_fav_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_fav_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_form.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_intermediate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_intermediate.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_local_library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_local_library.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_mode_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_mode_edit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_person_pin_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_person_pin_circle.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_shake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_shake.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_share_segment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_share_segment.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_star_border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_star_border.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_star_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_star_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_total_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_total_done.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_view_feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_view_feed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_walkthrough.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_walkthrough.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_walkthrough1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_walkthrough1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_walkthrough2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_walkthrough2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_walkthrough3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ic_walkthrough3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ir.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/login_umbrella.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/login_umbrella.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ru.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/ta.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/umbrella190.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/umbrella190.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/walktrough2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/walktrough2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/walktrough3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/walktrough3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/walktrough4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable-xxxhdpi/walktrough4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/baseline_search_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/collapse.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/collapse_animated.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/expand.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/expand_animated.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/favorite_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_action_back.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_dashboard_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable/ic_fav.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fav_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable/ic_fav_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_home_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/securityfirst/Umbrella_android/6856332bd2d12aceda147192475c4ca9e6ef67ff/app/src/main/res/drawable/ic_menu_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_notifications_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/about.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 18 | 19 | 20 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/account_skip_alert.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 23 | 24 | 32 | 33 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/layout/account_switch_server_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/checklist_custom_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 20 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/checklist_dashboard_footer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/layout/checklist_dashboard_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/layout/checklist_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/layout/checklist_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/difficulty_spinner_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/empty_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/feed_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/form_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_standard.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |