├── file.txt ├── native └── KotlinIOS │ ├── .idea │ ├── .name │ ├── .gitignore │ ├── xcode.xml │ ├── misc.xml │ ├── vcs.xml │ ├── modules.xml │ └── runConfigurations │ │ ├── Authentication.xml │ │ ├── KotlinIOS.xml │ │ └── KotlinIOSTests.xml │ ├── KotlinIOS │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── Primary.colorset │ │ │ └── Contents.json │ │ ├── secondary.colorset │ │ │ └── Contents.json │ │ ├── primaryLight.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Pods │ │ ├── Target Support Files │ │ │ └── Swinject │ │ │ │ ├── Swinject.modulemap │ │ │ │ ├── Swinject-dummy.m │ │ │ │ ├── Swinject-prefix.pch │ │ │ │ ├── Swinject-umbrella.h │ │ │ │ ├── Swinject.xcconfig │ │ │ │ └── Swinject-Info.plist │ │ ├── Swinject │ │ │ ├── Sources │ │ │ │ ├── FunctionType.swift │ │ │ │ ├── SpinLock.swift │ │ │ │ ├── GraphIdentifier.swift │ │ │ │ ├── Swinject.h │ │ │ │ ├── Container.Logging.swift │ │ │ │ ├── UnavailableItems.swift │ │ │ │ ├── Behavior.swift │ │ │ │ ├── Assembly.swift │ │ │ │ ├── _Resolver.swift │ │ │ │ ├── SynchronizedResolver.swift │ │ │ │ ├── ObjectScope.Standard.swift │ │ │ │ ├── Container.TypeForwarding.swift │ │ │ │ ├── ServiceKey.swift │ │ │ │ ├── ObjectScope.swift │ │ │ │ └── DebugHelper.swift │ │ │ └── LICENSE │ │ ├── Manifest.lock │ │ └── Pods.xcodeproj │ │ │ └── xcuserdata │ │ │ └── joebirch.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ ├── Podfile.lock │ ├── exportOptions.plist │ ├── MinimiseView.swift │ ├── ViewProvider.swift │ ├── DependencyAssembler.swift │ └── AppDelegate.swift │ ├── Gemfile │ ├── KotlinIOS.xcodeproj │ ├── project.xcworkspace │ │ ├── xcuserdata │ │ │ └── joebirch.xcuserdatad │ │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── joebirch.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── Minimise.xcworkspace │ ├── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist │ ├── xcuserdata │ │ └── joebirch.xcuserdatad │ │ │ ├── xcschemes │ │ │ └── xcschememanagement.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── contents.xcworkspacedata │ ├── Common │ ├── ViewFactory.swift │ ├── ScreenFactory.swift │ └── Info.plist │ ├── KotlinIOS.xcworkspace │ └── contents.xcworkspacedata │ ├── Creation │ ├── CreationViewFactory.swift │ ├── Creation.h │ └── Info.plist │ ├── Dashboard │ ├── DashboardViewModel.swift │ ├── DashboardViewFactory.swift │ ├── Dashboard.h │ └── Info.plist │ ├── Authentication │ ├── forgot_password │ │ └── ForgotPasswordView.swift │ ├── ViewController.swift │ ├── Authentication.h │ ├── Info.plist │ └── AuthenticationViewFactory.swift │ ├── Podfile.lock │ ├── KotlinIOSTests │ ├── Info.plist │ └── KotlinIOSTests.swift │ ├── KotlinIOSUITests │ ├── Info.plist │ └── KotlinIOSUITests.swift │ ├── DashboardTests │ ├── Info.plist │ └── DashboardTests.swift │ ├── AuthenticationTests │ ├── Info.plist │ ├── AuthenticationTests.swift │ └── AuthenticationViewModelTest.swift │ ├── KotlinIOS.xctestplan │ └── Podfile ├── platform_android ├── core │ ├── .gitignore │ ├── consumer-rules.pro │ ├── src │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── android │ │ │ └── core │ │ │ └── di │ │ │ ├── default.kt │ │ │ ├── BaseViewModel.kt │ │ │ ├── SingleLiveEvent.kt │ │ │ └── Preferences.kt │ ├── build.gradle │ └── proguard-rules.pro ├── common-ui │ ├── .gitignore │ ├── consumer-rules.pro │ ├── src │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── common_ui │ │ │ ├── Composablefactory.kt │ │ │ ├── layout.kt │ │ │ └── theme.kt │ ├── proguard-rules.pro │ └── build.gradle ├── creation │ ├── .gitignore │ └── src │ │ ├── main │ │ ├── res │ │ │ └── drawable │ │ │ │ ├── arrow_right.png │ │ │ │ ├── ic_baseline_arrow_forward_24.xml │ │ │ │ └── ic_baseline_arrow_back_24.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── creation │ │ │ └── CreationEvent.kt │ │ ├── debug │ │ └── java │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── creation │ │ │ └── CreationPreview.kt │ │ ├── androidTest │ │ └── java │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── creation │ │ │ └── CreationContentTest.kt │ │ └── test │ │ └── java │ │ └── co │ │ └── joebirch │ │ └── minimise │ │ └── creation │ │ ├── CreationViewModelTest.kt │ │ └── util.kt ├── dashboard │ ├── .gitignore │ ├── consumer-rules.pro │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── drawable │ │ │ │ │ ├── plus.png │ │ │ │ │ ├── ic_baseline_menu_24.xml │ │ │ │ │ ├── ic_baseline_add_24.xml │ │ │ │ │ ├── ic_baseline_close_24.xml │ │ │ │ │ ├── ic_four.xml │ │ │ │ │ ├── ic_menu.xml │ │ │ │ │ ├── ic_two.xml │ │ │ │ │ ├── ic_three.xml │ │ │ │ │ └── ic_one.xml │ │ │ │ ├── drawable-xxxhdpi │ │ │ │ │ └── outline_add_white_24dp.png │ │ │ │ └── values │ │ │ │ │ └── strings.xml │ │ │ ├── kotlin │ │ │ │ └── co │ │ │ │ │ └── joebirch │ │ │ │ │ └── minimise │ │ │ │ │ └── dashboard │ │ │ │ │ ├── MultiFabState.kt │ │ │ │ │ ├── MultiFabItem.kt │ │ │ │ │ └── Composablefactory.kt │ │ │ └── AndroidManifest.xml │ │ ├── test │ │ │ └── java │ │ │ │ └── co │ │ │ │ └── joebirch │ │ │ │ └── minimise │ │ │ │ └── dashboard │ │ │ │ └── ExampleUnitTest.kt │ │ └── androidTest │ │ │ └── java │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── dashboard │ │ │ └── ExampleInstrumentedTest.kt │ └── proguard-rules.pro ├── design │ ├── .gitignore │ ├── consumer-rules.pro │ ├── src │ │ └── main │ │ │ ├── res │ │ │ ├── font │ │ │ │ ├── poppins_black.ttf │ │ │ │ ├── poppins_bold.ttf │ │ │ │ ├── poppins_light.ttf │ │ │ │ ├── poppins_thin.ttf │ │ │ │ ├── poppins_medium.ttf │ │ │ │ ├── poppins_regular.ttf │ │ │ │ ├── poppins_extra_bold.ttf │ │ │ │ └── poppins_semi_bold.ttf │ │ │ ├── color │ │ │ │ └── selector_primary_button_text.xml │ │ │ ├── anim │ │ │ │ ├── bottom_sheet_slide_out.xml │ │ │ │ └── bottom_sheet_slide_in.xml │ │ │ ├── values │ │ │ │ ├── dimen.xml │ │ │ │ ├── motion.xml │ │ │ │ ├── styles.xml │ │ │ │ └── color.xml │ │ │ └── values-v23 │ │ │ │ └── themes.xml │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ └── proguard-rules.pro ├── navigation │ ├── .gitignore │ ├── consumer-rules.pro │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── co │ │ │ │ └── joebirch │ │ │ │ └── minimise │ │ │ │ └── navigation │ │ │ │ ├── NavigationCommand.kt │ │ │ │ ├── NavigationManager.kt │ │ │ │ ├── DashboardDirections.kt │ │ │ │ └── AuthenticationDirections.kt │ │ │ ├── AndroidManifest.xml │ │ │ └── res │ │ │ └── navigation │ │ │ └── dashboard.xml │ ├── proguard-rules.pro │ └── build.gradle ├── onboarding │ ├── .gitignore │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── values │ │ │ │ │ └── strings.xml │ │ │ │ └── layout │ │ │ │ │ └── fragment_onboarding.xml │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── co │ │ │ │ └── joebirch │ │ │ │ └── minimise │ │ │ │ └── onboarding │ │ │ │ └── OnboardingViewModel.kt │ │ ├── test │ │ │ └── java │ │ │ │ └── co │ │ │ │ └── joebirch │ │ │ │ └── minimise │ │ │ │ └── onboarding │ │ │ │ └── ExampleUnitTest.kt │ │ └── androidTest │ │ │ └── java │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── onboarding │ │ │ └── ExampleInstrumentedTest.kt │ └── build.gradle ├── authentication │ ├── .gitignore │ ├── consumer-rules.pro │ ├── src │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── co │ │ │ │ │ └── joebirch │ │ │ │ │ └── minimise │ │ │ │ │ └── authentication │ │ │ │ │ ├── AuthenticationEvent.kt │ │ │ │ │ ├── util │ │ │ │ │ └── AuthenticationValidator.kt │ │ │ │ │ ├── AuthenticationModule.kt │ │ │ │ │ └── reset_password │ │ │ │ │ └── ResetPasswordViewModel.kt │ │ │ └── res │ │ │ │ ├── navigation │ │ │ │ └── forgot_password_nav.xml │ │ │ │ └── values │ │ │ │ └── strings.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── test │ │ │ └── java │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── authentication │ │ │ └── AuthenticationValidatorTest.kt │ └── proguard-rules.pro └── app │ ├── .gitignore │ ├── src │ └── main │ │ ├── res │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── layout │ │ │ └── activity_main.xml │ │ └── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ ├── java │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── android │ │ │ ├── MinimiseApp.kt │ │ │ ├── MainState.kt │ │ │ ├── AppModule.kt │ │ │ └── MainViewModel.kt │ │ └── AndroidManifest.xml │ └── proguard-rules.pro ├── shared ├── SharedCommon │ ├── .gitignore │ ├── src │ │ └── commonMain │ │ │ └── kotlin │ │ │ └── co.joebirch.minimise.shared_common │ │ │ ├── di │ │ │ └── Provider.kt │ │ │ ├── SettingsRepository.kt │ │ │ ├── presentation │ │ │ └── UiState.kt │ │ │ └── interactor │ │ │ └── UseCase.kt │ ├── build.gradle.kts │ └── SharedCommon.podspec ├── SharedCore │ ├── .gitignore │ └── src │ │ └── commonMain │ │ └── kotlin │ │ └── co.joebirch.minimise.shared_core │ │ └── MinimiseApp.kt ├── SharedCreation │ ├── .gitignore │ ├── consumer-rules.pro │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ └── values │ │ │ │ │ └── strings.xml │ │ │ └── AndroidManifest.xml │ │ ├── commonMain │ │ │ └── kotlin │ │ │ │ └── co.joebirch.minimise.dashboard │ │ │ │ ├── ItemType.kt │ │ │ │ ├── CreationStep.kt │ │ │ │ └── CreationState.kt │ │ ├── commonTest │ │ │ └── kotlin │ │ │ │ └── co.joebirch.minimise.shared_authentication │ │ │ │ └── TestUtil.kt │ │ ├── iosTest │ │ │ └── kotlin │ │ │ │ └── co │ │ │ │ └── joebirch │ │ │ │ └── minimise │ │ │ │ └── shared_authentication │ │ │ │ └── TestUtil.kt │ │ └── androidTest │ │ │ └── kotlin │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── shared_authentication │ │ │ └── TestUtil.kt │ ├── proguard-rules.pro │ └── SharedCreation.podspec ├── SharedDashboard │ ├── consumer-rules.pro │ ├── .gitignore │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ └── values │ │ │ │ │ └── strings.xml │ │ │ └── AndroidManifest.xml │ │ ├── commonMain │ │ │ └── kotlin │ │ │ │ └── co.joebirch.minimise.shared.dashboard │ │ │ │ ├── DashboardView.kt │ │ │ │ ├── Belonging.kt │ │ │ │ ├── Category.kt │ │ │ │ └── DashboardState.kt │ │ ├── commonTest │ │ │ └── kotlin │ │ │ │ └── co.joebirch.minimise.shared_authentication │ │ │ │ └── TestUtil.kt │ │ ├── iosTest │ │ │ └── kotlin │ │ │ │ └── co │ │ │ │ └── joebirch │ │ │ │ └── minimise │ │ │ │ └── shared_authentication │ │ │ │ └── TestUtil.kt │ │ └── androidTest │ │ │ └── kotlin │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── shared_authentication │ │ │ └── TestUtil.kt │ ├── proguard-rules.pro │ └── SharedDashboard.podspec └── SharedAuthentication │ ├── consumer-rules.pro │ ├── .gitignore │ ├── src │ ├── main │ │ ├── res │ │ │ └── values │ │ │ │ └── strings.xml │ │ └── AndroidManifest.xml │ ├── commonTest │ │ └── kotlin │ │ │ └── co.joebirch.minimise.shared_authentication │ │ │ ├── TestUtil.kt │ │ │ ├── mapper │ │ │ └── MockResetPasswordResponseMapper.kt │ │ │ ├── util │ │ │ ├── DataFactory.kt │ │ │ ├── MockAuthenticationStore.kt │ │ │ └── AuthenticationResponseFactory.kt │ │ │ ├── MockAuthenticationDataRepository.kt │ │ │ ├── interactor │ │ │ └── AuthTest.kt │ │ │ └── AuthenticationDataRepositoryTest.kt │ ├── commonMain │ │ ├── kotlin │ │ │ └── co.joebirch.minimise.authentication │ │ │ │ ├── ResetPasswordView.kt │ │ │ │ ├── AuthenticateMode.kt │ │ │ │ ├── model │ │ │ │ ├── AuthenticationModel.kt │ │ │ │ ├── ResetPasswordResponse.kt │ │ │ │ └── ResetPasswordResponseModel.kt │ │ │ │ ├── AuthenticateView.kt │ │ │ │ ├── remote │ │ │ │ ├── AuthenticationRemote.kt │ │ │ │ └── AuthenticationRemoteStore.kt │ │ │ │ ├── mapper │ │ │ │ ├── ResetPasswordResponseMapper.kt │ │ │ │ └── AuthenticationResponseMapper.kt │ │ │ │ ├── RepositoriesProvider.kt │ │ │ │ ├── ResetPasswordState.kt │ │ │ │ ├── forgot_password │ │ │ │ └── ForgotPasswordState.kt │ │ │ │ ├── AuthenticationRepository.kt │ │ │ │ ├── AuthenticationDataRepository.kt │ │ │ │ ├── AuthenticationState.kt │ │ │ │ └── interactor │ │ │ │ └── ResetPassword.kt │ │ └── graphql │ │ │ └── co.joebirch.minimise │ │ │ ├── SignUp.graphql │ │ │ └── SignIn.graphql │ ├── iosTest │ │ └── kotlin │ │ │ └── co │ │ │ └── joebirch │ │ │ └── minimise │ │ │ └── shared_authentication │ │ │ └── TestUtil.kt │ └── androidTest │ │ └── kotlin │ │ └── co │ │ └── joebirch │ │ └── minimise │ │ └── shared_authentication │ │ └── TestUtil.kt │ ├── proguard-rules.pro │ └── SharedAuthentication.podspec ├── art └── screenshots.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .github ├── secrets │ ├── Certificates.p12.gpg │ ├── github_actions.mobileprovision.gpg │ └── decrypt_secrets.sh ├── scripts │ ├── publish_testflight.sh │ ├── archive_app.sh │ ├── export_ipa.sh │ └── create_android_pr_ui_commands.sh └── workflows │ ├── shared_code_pr_workflow.yml │ ├── ios_pr_workflow.yaml │ ├── android-pr-workflow.yml │ └── ios_beta_release.yaml ├── .gitignore ├── settings.gradle ├── README.md └── gradle.properties /file.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /native/KotlinIOS/.idea/.name: -------------------------------------------------------------------------------- 1 | Minimise -------------------------------------------------------------------------------- /platform_android/core/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /platform_android/common-ui/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /platform_android/core/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /platform_android/creation/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /platform_android/dashboard/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /platform_android/design/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /platform_android/design/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shared/SharedCommon/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /shared/SharedCore/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /shared/SharedCreation/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /shared/SharedCreation/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shared/SharedDashboard/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /platform_android/common-ui/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /platform_android/dashboard/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /platform_android/navigation/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /platform_android/navigation/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /platform_android/onboarding/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /shared/SharedAuthentication/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shared/SharedDashboard/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /platform_android/authentication/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /platform_android/authentication/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /platform_android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | google-services.json -------------------------------------------------------------------------------- /native/KotlinIOS/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml 3 | -------------------------------------------------------------------------------- /art/screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/art/screenshots.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.github/secrets/Certificates.p12.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/.github/secrets/Certificates.p12.gpg -------------------------------------------------------------------------------- /shared/SharedCreation/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Data 3 | 4 | -------------------------------------------------------------------------------- /shared/SharedDashboard/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Data 3 | 4 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Data 3 | 4 | -------------------------------------------------------------------------------- /.github/secrets/github_actions.mobileprovision.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/.github/secrets/github_actions.mobileprovision.gpg -------------------------------------------------------------------------------- /platform_android/authentication/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /shared/SharedCore/src/commonMain/kotlin/co.joebirch.minimise.shared_core/MinimiseApp.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_core 2 | 3 | object MinimiseApp { 4 | 5 | } -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/dashboard/src/main/res/drawable/plus.png -------------------------------------------------------------------------------- /platform_android/design/src/main/res/font/poppins_black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/design/src/main/res/font/poppins_black.ttf -------------------------------------------------------------------------------- /platform_android/design/src/main/res/font/poppins_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/design/src/main/res/font/poppins_bold.ttf -------------------------------------------------------------------------------- /platform_android/design/src/main/res/font/poppins_light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/design/src/main/res/font/poppins_light.ttf -------------------------------------------------------------------------------- /platform_android/design/src/main/res/font/poppins_thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/design/src/main/res/font/poppins_thin.ttf -------------------------------------------------------------------------------- /shared/SharedCreation/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /shared/SharedDashboard/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform_android/design/src/main/res/font/poppins_medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/design/src/main/res/font/poppins_medium.ttf -------------------------------------------------------------------------------- /platform_android/design/src/main/res/font/poppins_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/design/src/main/res/font/poppins_regular.ttf -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /platform_android/creation/src/main/res/drawable/arrow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/creation/src/main/res/drawable/arrow_right.png -------------------------------------------------------------------------------- /platform_android/design/src/main/res/font/poppins_extra_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/design/src/main/res/font/poppins_extra_bold.ttf -------------------------------------------------------------------------------- /platform_android/design/src/main/res/font/poppins_semi_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/design/src/main/res/font/poppins_semi_bold.ttf -------------------------------------------------------------------------------- /shared/SharedCommon/src/commonMain/kotlin/co.joebirch.minimise.shared_common/di/Provider.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_common.di 2 | 3 | abstract class Provider { 4 | 5 | } -------------------------------------------------------------------------------- /shared/SharedCreation/src/commonMain/kotlin/co.joebirch.minimise.dashboard/ItemType.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.dashboard 2 | 3 | enum class ItemType { 4 | OWNED, PURCHASE 5 | } -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform_android/creation/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /platform_android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | KotlinMPP 3 | Onboarding 4 | 5 | -------------------------------------------------------------------------------- /platform_android/common-ui/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/kotlin/co/joebirch/minimise/dashboard/MultiFabState.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.dashboard 2 | 3 | enum class MultiFabState { 4 | COLLAPSED, EXPANDED 5 | } -------------------------------------------------------------------------------- /native/KotlinIOS/.idea/xcode.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /platform_android/core/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | / 5 | -------------------------------------------------------------------------------- /shared/SharedCommon/src/commonMain/kotlin/co.joebirch.minimise.shared_common/SettingsRepository.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_common 2 | 3 | 4 | class SettingsRepository() { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/* 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | .idea 11 | native/KotlinIOS/GoogleService-Info.plist 12 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | / 5 | -------------------------------------------------------------------------------- /platform_android/design/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | / 5 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Target Support Files/Swinject/Swinject.modulemap: -------------------------------------------------------------------------------- 1 | framework module Swinject { 2 | umbrella header "Swinject-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Target Support Files/Swinject/Swinject-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Swinject : NSObject 3 | @end 4 | @implementation PodsDummy_Swinject 5 | @end 6 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable-xxxhdpi/outline_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/platform_android/dashboard/src/main/res/drawable-xxxhdpi/outline_add_white_24dp.png -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello blank fragment 4 | -------------------------------------------------------------------------------- /native/KotlinIOS/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /native/KotlinIOS/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | source 'https://rubygems.org' do 4 | gem 'cocoapods', '~> 1.0' 5 | gem 'xcodeproj', :git => 'https://github.com/CocoaPods/Xcodeproj.git', :branch => 'master' 6 | end -------------------------------------------------------------------------------- /native/KotlinIOS/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/FunctionType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | // Type alias to expect a closure. 6 | internal typealias FunctionType = Any 7 | -------------------------------------------------------------------------------- /.github/scripts/publish_testflight.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | cd native/KotlinIOS 6 | 7 | xcrun altool --upload-app -t ios -f DerivedData/Build/KotlinIOS.ipa -u "$APPLEID_USERNAME" -p "$APPLEID_PASSWORD" --verbose 8 | -------------------------------------------------------------------------------- /shared/SharedDashboard/src/commonMain/kotlin/co.joebirch.minimise.shared.dashboard/DashboardView.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared.dashboard 2 | 3 | interface DashboardView { 4 | 5 | fun setSelectedCategory(category: Category) 6 | } -------------------------------------------------------------------------------- /shared/SharedDashboard/src/commonMain/kotlin/co.joebirch.minimise.shared.dashboard/Belonging.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared.dashboard 2 | 3 | class Belonging( 4 | val id: String, 5 | val name: String, 6 | val store: String 7 | ) -------------------------------------------------------------------------------- /shared/SharedCreation/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | @Suppress("UnusedPrivateMember") 4 | internal expect fun runTest(block: suspend () -> T) -------------------------------------------------------------------------------- /shared/SharedDashboard/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | @Suppress("UnusedPrivateMember") 4 | internal expect fun runTest(block: suspend () -> T) -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | @Suppress("UnusedPrivateMember") 4 | internal expect fun runTest(block: suspend () -> T) -------------------------------------------------------------------------------- /platform_android/authentication/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/ResetPasswordView.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | interface ResetPasswordView { 4 | 5 | fun resetPassword( 6 | emailAddress: String 7 | ) 8 | } -------------------------------------------------------------------------------- /platform_android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /platform_android/core/src/main/java/co/joebirch/minimise/android/core/di/default.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.android.core.di 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | 5 | fun MutableLiveData.default(initialValue: T) = apply { setValue(initialValue) } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/AuthenticateMode.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | sealed class AuthenticateMode { 4 | object SignUp: AuthenticateMode() 5 | object SignIn: AuthenticateMode() 6 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS.xcodeproj/project.xcworkspace/xcuserdata/joebirch.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hitherejoe/minimise/HEAD/native/KotlinIOS/KotlinIOS.xcodeproj/project.xcworkspace/xcuserdata/joebirch.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /platform_android/onboarding/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello blank fragment 5 | Continue 6 | 7 | 8 | -------------------------------------------------------------------------------- /shared/SharedCreation/src/iosTest/kotlin/co/joebirch/minimise/shared_authentication/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | import kotlinx.coroutines.runBlocking 4 | 5 | internal actual fun runTest(block: suspend () -> T) { 6 | runBlocking { block() } 7 | } -------------------------------------------------------------------------------- /shared/SharedDashboard/src/iosTest/kotlin/co/joebirch/minimise/shared_authentication/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | import kotlinx.coroutines.runBlocking 4 | 5 | internal actual fun runTest(block: suspend () -> T) { 6 | runBlocking { block() } 7 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Apr 16 20:40:33 BST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-rc-1-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/iosTest/kotlin/co/joebirch/minimise/shared_authentication/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | import kotlinx.coroutines.runBlocking 4 | 5 | internal actual fun runTest(block: suspend () -> T) { 6 | runBlocking { block() } 7 | } -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/kotlin/co/joebirch/minimise/dashboard/MultiFabItem.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.dashboard 2 | 3 | import androidx.compose.ui.graphics.ImageBitmap 4 | 5 | class MultiFabItem( 6 | val identifier: String, 7 | val icon: ImageBitmap, 8 | val label: String 9 | ) -------------------------------------------------------------------------------- /shared/SharedCommon/src/commonMain/kotlin/co.joebirch.minimise.shared_common/presentation/UiState.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_common.presentation 2 | 3 | abstract class UiState( 4 | open val isLoading: Boolean, 5 | open val success: Boolean, 6 | open val errorMessage: String? 7 | ) -------------------------------------------------------------------------------- /platform_android/core/src/main/java/co/joebirch/minimise/android/core/di/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.android.core.di 2 | 3 | import androidx.lifecycle.ViewModel 4 | 5 | abstract class BaseViewModel : ViewModel() { 6 | 7 | 8 | fun navigate( 9 | ) { 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/model/AuthenticationModel.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.model 2 | 3 | data class AuthenticationModel( 4 | val token: String? = null, 5 | val message: String? = null, 6 | val errorCode: Int? = null 7 | ) -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/model/ResetPasswordResponse.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.model 2 | 3 | data class ResetPasswordResponse( 4 | val success: Boolean = false, 5 | val message: String? = null, 6 | val errorCode: Int? = null 7 | ) -------------------------------------------------------------------------------- /native/KotlinIOS/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/kotlin/co/joebirch/minimise/dashboard/Composablefactory.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.dashboard 2 | 3 | import androidx.compose.runtime.Composable 4 | 5 | abstract class Composablefactory constructor() { 6 | 7 | @Composable abstract fun Content(viewModel: ViewModel) 8 | 9 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Target Support Files/Swinject/Swinject-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /native/KotlinIOS/Minimise.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /platform_android/design/src/main/res/color/selector_primary_button_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /platform_android/navigation/src/main/java/co/joebirch/minimise/navigation/NavigationCommand.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.navigation 2 | 3 | import androidx.navigation.compose.NamedNavArgument 4 | 5 | interface NavigationCommand { 6 | 7 | val arguments: List 8 | 9 | val destination: String 10 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/model/ResetPasswordResponseModel.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.model 2 | 3 | data class ResetPasswordResponseModel( 4 | val success: Boolean = false, 5 | val message: String? = null, 6 | val errorCode: Int? = null 7 | ) -------------------------------------------------------------------------------- /native/KotlinIOS/Common/ViewFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewFactory.swift 3 | // Common 4 | // 5 | // Created by Joe Birch on 26/04/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | 12 | public protocol ViewFactory { 13 | func make() -> AnyView 14 | } 15 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /native/KotlinIOS/Minimise.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /platform_android/common-ui/src/main/java/co/joebirch/minimise/common_ui/Composablefactory.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.common_ui 2 | 3 | import androidx.compose.runtime.Composable 4 | 5 | abstract class Composablefactory { 6 | 7 | @Composable abstract fun Content( 8 | viewModel: ViewModel 9 | ) 10 | 11 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /platform_android/app/src/main/java/co/joebirch/minimise/android/MinimiseApp.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.android 2 | 3 | import android.app.Application 4 | import dagger.hilt.android.HiltAndroidApp 5 | 6 | @HiltAndroidApp 7 | class MinimiseApp : Application() { 8 | 9 | override fun onCreate() { 10 | super.onCreate() 11 | } 12 | } -------------------------------------------------------------------------------- /platform_android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /shared/SharedCommon/src/commonMain/kotlin/co.joebirch.minimise.shared_common/interactor/UseCase.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_common.interactor 2 | 3 | abstract class UseCase { 4 | 5 | abstract fun run(params: Params, completion: (T) -> Unit) 6 | 7 | abstract fun runWithoutThreading(params: Params, completion: (T) -> Unit) 8 | 9 | } -------------------------------------------------------------------------------- /shared/SharedDashboard/src/commonMain/kotlin/co.joebirch.minimise.shared.dashboard/Category.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared.dashboard 2 | 3 | sealed class Category(val title: String, val key: String) { 4 | 5 | object PendingBelongings : Category("Pending", "pending_belongings") 6 | 7 | object Belongings : Category("Belongings", "owned_belongings") 8 | 9 | } -------------------------------------------------------------------------------- /platform_android/creation/src/debug/java/co/joebirch/minimise/creation/CreationPreview.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.creation 2 | 3 | import androidx.compose.material.Text 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.tooling.preview.Preview 6 | 7 | @Preview 8 | @Composable 9 | fun TutorialPreview() { 10 | Text("Hello") 11 | } 12 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Swinject (2.7.1) 3 | 4 | DEPENDENCIES: 5 | - Swinject 6 | 7 | SPEC REPOS: 8 | https://github.com/CocoaPods/Specs.git: 9 | - Swinject 10 | 11 | SPEC CHECKSUMS: 12 | Swinject: ddf78b8486dd9b71a667b852cad919ab4484478e 13 | 14 | PODFILE CHECKSUM: 375e0c798dd52ec8e959756e95d270770d00662f 15 | 16 | COCOAPODS: 1.8.4 17 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Swinject (2.7.1) 3 | 4 | DEPENDENCIES: 5 | - Swinject 6 | 7 | SPEC REPOS: 8 | https://github.com/CocoaPods/Specs.git: 9 | - Swinject 10 | 11 | SPEC CHECKSUMS: 12 | Swinject: ddf78b8486dd9b71a667b852cad919ab4484478e 13 | 14 | PODFILE CHECKSUM: 375e0c798dd52ec8e959756e95d270770d00662f 15 | 16 | COCOAPODS: 1.8.4 17 | -------------------------------------------------------------------------------- /.github/scripts/archive_app.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | cd native/KotlinIOS 6 | 7 | xcodebuild -workspace KotlinIOS.xcworkspace \ 8 | -scheme KotlinIOS \ 9 | -sdk iphoneos \ 10 | -configuration Release \ 11 | -derivedDataPath DerivedData \ 12 | -archivePath DerivedData/Archive/Minimise \ 13 | clean archive 14 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/graphql/co.joebirch.minimise/SignUp.graphql: -------------------------------------------------------------------------------- 1 | mutation SignUp( 2 | $emailAddress: String! 3 | $password: String! 4 | ) { 5 | createUser(userInput: { 6 | email: $emailAddress, password: $password 7 | }) { 8 | ... on AuthenticationError { 9 | message 10 | } 11 | ... on AuthData { 12 | token 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /shared/SharedCreation/src/androidTest/kotlin/co/joebirch/minimise/shared_authentication/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | import kotlinx.coroutines.ExperimentalCoroutinesApi 4 | import kotlinx.coroutines.test.runBlockingTest 5 | 6 | @UseExperimental(ExperimentalCoroutinesApi::class) 7 | internal actual fun runTest(block: suspend () -> T) { 8 | runBlockingTest { block() } 9 | } -------------------------------------------------------------------------------- /shared/SharedDashboard/src/androidTest/kotlin/co/joebirch/minimise/shared_authentication/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | import kotlinx.coroutines.ExperimentalCoroutinesApi 4 | import kotlinx.coroutines.test.runBlockingTest 5 | 6 | @UseExperimental(ExperimentalCoroutinesApi::class) 7 | internal actual fun runTest(block: suspend () -> T) { 8 | runBlockingTest { block() } 9 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/SpinLock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | internal final class SpinLock { 8 | private let lock = NSRecursiveLock() 9 | 10 | func sync(action: () -> T) -> T { 11 | lock.lock() 12 | defer { lock.unlock() } 13 | return action() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable/ic_baseline_menu_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/androidTest/kotlin/co/joebirch/minimise/shared_authentication/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | import kotlinx.coroutines.ExperimentalCoroutinesApi 4 | import kotlinx.coroutines.test.runBlockingTest 5 | 6 | @UseExperimental(ExperimentalCoroutinesApi::class) 7 | internal actual fun runTest(block: suspend () -> T) { 8 | runBlockingTest { block() } 9 | } -------------------------------------------------------------------------------- /platform_android/creation/src/main/res/drawable/ic_baseline_arrow_forward_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/AuthenticateView.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | interface AuthenticateView { 4 | 5 | fun authenticate() 6 | 7 | fun signUp() 8 | 9 | fun signIn() 10 | 11 | fun toggleAuthenticationMode() 12 | 13 | fun setEmailAddress(emailAddress: String) 14 | 15 | fun setPassword(password: String) 16 | } -------------------------------------------------------------------------------- /.github/scripts/export_ipa.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | cd native/KotlinIOS 6 | 7 | ls 8 | 9 | xcodebuild -archivePath DerivedData/Archive/Minimise.xcarchive \ 10 | -exportOptionsPlist KotlinIOS/exportOptions.plist \ 11 | -exportPath DerivedData/Build \ 12 | -allowProvisioningUpdates \ 13 | -exportArchive | xcpretty 14 | 15 | 16 | ls DerivedData/Build 17 | -------------------------------------------------------------------------------- /platform_android/creation/src/main/res/drawable/ic_baseline_arrow_back_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /platform_android/creation/src/androidTest/java/co/joebirch/minimise/creation/CreationContentTest.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.creation 2 | 3 | import androidx.compose.foundation.layout.ExperimentalLayout 4 | import androidx.test.filters.MediumTest 5 | import org.junit.runner.RunWith 6 | import org.junit.runners.JUnit4 7 | 8 | @ExperimentalLayout 9 | @MediumTest 10 | @RunWith(JUnit4::class) 11 | class CreationContentTest { 12 | 13 | } -------------------------------------------------------------------------------- /platform_android/app/src/main/java/co/joebirch/minimise/android/MainState.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.android 2 | 3 | sealed class MainState( 4 | val loading: Boolean = true, 5 | val isAuthenticated: Boolean = false 6 | ) { 7 | 8 | object Loading : MainState(loading = true) 9 | 10 | object Authenticated : MainState(isAuthenticated = true) 11 | 12 | object NotAuthenticated : MainState(isAuthenticated = false) 13 | 14 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/mapper/MockResetPasswordResponseMapper.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication.mapper 2 | 3 | import co.joebirch.minimise.authentication.mapper.ResetPasswordResponseMapper 4 | import co.joebirch.minimise.authentication.model.ResetPasswordResponse 5 | 6 | internal class MockResetPasswordResponseMapper : ResetPasswordResponseMapper() { 7 | 8 | 9 | } -------------------------------------------------------------------------------- /platform_android/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /native/KotlinIOS/Common/ScreenFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewProvider.swift 3 | // Common 4 | // 5 | // Created by Joe Birch on 29/04/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | 12 | public protocol ScreenFactory { 13 | func makeDashboardView() -> AnyView 14 | 15 | func makeAuthenticationView() -> AnyView 16 | 17 | func makeCreationView() -> AnyView 18 | } 19 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable/ic_baseline_add_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /platform_android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /platform_android/creation/src/test/java/co/joebirch/minimise/creation/CreationViewModelTest.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.creation 2 | 3 | import androidx.arch.core.executor.testing.InstantTaskExecutorRule 4 | import org.junit.Test 5 | 6 | import org.junit.Assert.* 7 | import org.junit.Rule 8 | 9 | class CreationViewModelTest { 10 | 11 | @get:Rule 12 | @Suppress("unused") 13 | var instantTaskExecutorRule = InstantTaskExecutorRule() 14 | 15 | 16 | } -------------------------------------------------------------------------------- /platform_android/design/src/main/res/anim/bottom_sheet_slide_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Target Support Files/Swinject/Swinject-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "Swinject.h" 14 | 15 | FOUNDATION_EXPORT double SwinjectVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char SwinjectVersionString[]; 17 | 18 | -------------------------------------------------------------------------------- /platform_android/design/src/main/res/anim/bottom_sheet_slide_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.github/workflows/shared_code_pr_workflow.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'shared/**' 7 | 8 | jobs: 9 | 10 | test: 11 | name: Run all Unit Tests 12 | runs-on: ubuntu-18.04 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: set up JDK 1.8 17 | uses: actions/setup-java@v1 18 | with: 19 | java-version: 1.8 20 | - name: Unit tests 21 | run: bash ./gradlew allTests 22 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Assets.xcassets/Primary.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0x7D", 9 | "green" : "0x57", 10 | "red" : "0x3B" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Assets.xcassets/secondary.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0x73", 9 | "green" : "0x5D", 10 | "red" : "0xC0" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/ios_pr_workflow.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'native/KotlinIOS/Authentication/**' 7 | jobs: 8 | 9 | test: 10 | name: Run all Unit Tests 11 | runs-on: macos-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Unit tests 16 | run: cd native/KotlinIOS xcodebuild -workspace Minimise.xcworkspace -scheme Authentication -destination 'platform=iOS Simulator,name=iPhone 11' test 17 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Assets.xcassets/primaryLight.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0xD4", 9 | "green" : "0x52", 10 | "red" : "0xAE" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /platform_android/navigation/src/main/java/co/joebirch/minimise/navigation/NavigationManager.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.navigation 2 | 3 | import co.joebirch.minimise.navigation.AuthenticationDirections.Default 4 | import kotlinx.coroutines.flow.MutableStateFlow 5 | 6 | class NavigationManager { 7 | 8 | var commands = MutableStateFlow(Default) 9 | 10 | fun navigate( 11 | directions: NavigationCommand 12 | ) { 13 | commands.value = directions 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/util/DataFactory.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication.util 2 | 3 | object DataFactory { 4 | 5 | fun randomString(): String { 6 | val allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz" 7 | return (1..20) 8 | .map { allowedChars.random() } 9 | .joinToString("") 10 | } 11 | 12 | fun randomInt() = (1..500).shuffled().first() 13 | } -------------------------------------------------------------------------------- /native/KotlinIOS/Minimise.xcworkspace/xcuserdata/joebirch.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | KotlinIOSTests.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 2 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/test/java/co/joebirch/minimise/dashboard/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.dashboard 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /platform_android/onboarding/src/test/java/co/joebirch/minimise/onboarding/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.onboarding 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /native/KotlinIOS/Creation/CreationViewFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CreationViewFactory.swift 3 | // Creation 4 | // 5 | // Created by Joe Birch on 02/05/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | import Common 12 | 13 | public struct CreationViewFactory : ViewFactory { 14 | 15 | public init() { 16 | 17 | } 18 | 19 | public func make() -> AnyView { 20 | return AnyView(CreationView()) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /platform_android/design/build.gradle: -------------------------------------------------------------------------------- 1 | import co.joebirch.minimise.buildsrc.* 2 | 3 | apply plugin: 'com.android.library' 4 | apply plugin: 'kotlin-android' 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion Versions.compileSdk 9 | 10 | defaultConfig { 11 | 12 | minSdkVersion Versions.minSdk 13 | targetSdkVersion Versions.targetSdk 14 | } 15 | } 16 | 17 | dependencies { 18 | implementation Deps.Kotlin.stdLib 19 | api Deps.Google.material 20 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/graphql/co.joebirch.minimise/SignIn.graphql: -------------------------------------------------------------------------------- 1 | query SignIn( 2 | $emailAddress: String! 3 | $password: String! 4 | ) { 5 | login(userInput: { 6 | email: $emailAddress, password: $password 7 | }) { 8 | ... on ExistingAccountError { 9 | message 10 | code 11 | } 12 | ... on AuthenticationError { 13 | message 14 | code 15 | } 16 | ... on AuthData { 17 | token 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable/ic_baseline_close_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /platform_android/onboarding/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /platform_android/onboarding/src/main/java/co/joebirch/minimise/onboarding/OnboardingViewModel.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.onboarding 2 | 3 | import androidx.hilt.lifecycle.ViewModelInject 4 | import androidx.lifecycle.SavedStateHandle 5 | import co.joebirch.minimise.android.core.di.BaseViewModel 6 | import dagger.hilt.android.lifecycle.HiltViewModel 7 | import javax.inject.Inject 8 | 9 | @HiltViewModel 10 | class OnboardingViewModel @Inject constructor( 11 | private val savedStateHandle: SavedStateHandle 12 | ) : BaseViewModel() -------------------------------------------------------------------------------- /platform_android/app/src/main/java/co/joebirch/minimise/android/AppModule.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.android 2 | 3 | import co.joebirch.minimise.navigation.NavigationManager 4 | import dagger.Module 5 | import dagger.Provides 6 | import dagger.hilt.InstallIn 7 | import dagger.hilt.components.SingletonComponent 8 | import javax.inject.Singleton 9 | 10 | @Module 11 | @InstallIn(SingletonComponent::class) 12 | class AppModule { 13 | 14 | @Singleton 15 | @Provides 16 | fun providesNavigationManager() = NavigationManager() 17 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Pods.xcodeproj/xcuserdata/joebirch.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Swinject.xcscheme 8 | 9 | isShown 10 | 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /platform_android/navigation/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 7 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/exportOptions.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | method 6 | app-store 7 | uploadBitcode 8 | 9 | uploadSymbols 10 | 11 | provisioningProfiles 12 | 13 | co.joebirch.minimise 14 | 3bd14cf8-32e9-44ca-b37e-ad910d0d975f 15 | 16 | 17 | -------------------------------------------------------------------------------- /native/KotlinIOS/Minimise.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /platform_android/design/src/main/res/values/dimen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16sp 4 | 24sp 5 | 22sp 6 | 32sp 7 | 18sp 8 | 14sp 9 | 12sp 10 | 11sp 11 | 20sp 12 | -------------------------------------------------------------------------------- /platform_android/onboarding/src/androidTest/java/co/joebirch/minimise/onboarding/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.onboarding 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | 7 | /** 8 | * Instrumented test, which will execute on an Android device. 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | @RunWith(AndroidJUnit4::class) 13 | class ExampleInstrumentedTest { 14 | @Test 15 | fun useAppContext() { 16 | } 17 | } -------------------------------------------------------------------------------- /native/KotlinIOS/Dashboard/DashboardViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DashboardViewModel.swift 3 | // Dashboard 4 | // 5 | // Created by Joe Birch on 23/04/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | 12 | class DashboardViewModel: ObservableObject { 13 | 14 | 15 | 16 | 17 | init() { 18 | 19 | } 20 | 21 | func setSelectedIndex(index: Int) { 22 | 23 | } 24 | 25 | private func handleBelongingsLoaded() { 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/GraphIdentifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | /// Unique identifier of an object graph during a resolution process. 6 | public final class GraphIdentifier {} 7 | 8 | extension GraphIdentifier: Equatable, Hashable { 9 | public static func == (lhs: GraphIdentifier, rhs: GraphIdentifier) -> Bool { 10 | return lhs === rhs 11 | } 12 | 13 | public func hash(into hasher: inout Hasher) { 14 | hasher.combine(ObjectIdentifier(self).hashValue) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /native/KotlinIOS/Authentication/forgot_password/ForgotPasswordView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ForgotPasswordView.swift 3 | // Authentication 4 | // 5 | // Created by Joe Birch on 29/02/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ForgotPasswordView: View { 12 | var body: some View { 13 | Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) 14 | } 15 | } 16 | 17 | struct ForgotPasswordView_Previews: PreviewProvider { 18 | static var previews: some View { 19 | ForgotPasswordView() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /native/KotlinIOS/Authentication/ViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SharedAuthentication 3 | 4 | class ViewController: UIViewController { 5 | 6 | let viewModel = AuthenticationViewModel(authenticate: Authenticate()) 7 | 8 | override func viewDidLoad() { 9 | super.viewDidLoad() 10 | 11 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 21)) 12 | label.center = CGPoint(x: 160, y: 285) 13 | label.textAlignment = .center 14 | label.font = label.font.withSize(25) 15 | view.addSubview(label) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /platform_android/authentication/src/main/kotlin/co/joebirch/minimise/authentication/AuthenticationEvent.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | sealed class AuthenticationEvent { 4 | 5 | object AuthenticationModeToggled : AuthenticationEvent() 6 | object DismissErrorDialog : AuthenticationEvent() 7 | object AuthenticateClicked : AuthenticationEvent() 8 | object ForgotPasswordClicked : AuthenticationEvent() 9 | data class EmailChanged(val email: String) : AuthenticationEvent() 10 | data class PasswordChanged(val password: String) : AuthenticationEvent() 11 | 12 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':platform_android:creation' 2 | include ':platform_android:common-ui' 3 | include ':platform_android:dashboard' 4 | include ':platform_android:design' 5 | include ':platform_android:core' 6 | include ':platform_android:onboarding' 7 | include ':platform_android:navigation' 8 | include ':platform_android:app' 9 | include ':platform_android:authentication' 10 | 11 | include ':shared:SharedAuthentication' 12 | include ':shared:SharedCommon' 13 | include ':shared:SharedCore' 14 | include ':shared:SharedCreation' 15 | include ':shared:SharedDashboard' 16 | 17 | rootProject.name='Minimise' -------------------------------------------------------------------------------- /native/KotlinIOS/Creation/Creation.h: -------------------------------------------------------------------------------- 1 | // 2 | // Creation.h 3 | // Creation 4 | // 5 | // Created by Joe Birch on 02/05/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for Creation. 12 | FOUNDATION_EXPORT double CreationVersionNumber; 13 | 14 | //! Project version string for Creation. 15 | FOUNDATION_EXPORT const unsigned char CreationVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Target Support Files/Swinject/Swinject.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Swinject 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Swinject 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 11 | -------------------------------------------------------------------------------- /native/KotlinIOS/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SharedAuthentication (1.0) 3 | - Swinject (2.7.1) 4 | 5 | DEPENDENCIES: 6 | - SharedAuthentication (from `../../shared/SharedAuthentication`) 7 | - Swinject 8 | 9 | SPEC REPOS: 10 | trunk: 11 | - Swinject 12 | 13 | EXTERNAL SOURCES: 14 | SharedAuthentication: 15 | :path: "../../shared/SharedAuthentication" 16 | 17 | SPEC CHECKSUMS: 18 | SharedAuthentication: 51ad694e0ad7c0f6183dbc10364b5cd9c2784f7c 19 | Swinject: ddf78b8486dd9b71a667b852cad919ab4484478e 20 | 21 | PODFILE CHECKSUM: 41eba831a847eee1b19a6518dcb18edf64d1f56d 22 | 23 | COCOAPODS: 1.9.1 24 | -------------------------------------------------------------------------------- /platform_android/authentication/src/main/kotlin/co/joebirch/minimise/authentication/util/AuthenticationValidator.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.util 2 | 3 | import javax.inject.Inject 4 | 5 | class AuthenticationValidator @Inject constructor() { 6 | 7 | fun validateInputData( 8 | password: String, 9 | emailAddress: String 10 | ): Boolean { 11 | return password.isNotEmpty() && validateEmailAddress(emailAddress) 12 | } 13 | 14 | fun validateEmailAddress( 15 | emailAddress: String 16 | ): Boolean { 17 | return emailAddress.isNotEmpty() 18 | } 19 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/Swinject.h: -------------------------------------------------------------------------------- 1 | // 2 | // Swinject.h 3 | // Swinject 4 | // 5 | // Created by Yoichi Tagaya on 7/22/15. 6 | // Copyright © 2015 Swinject Contributors. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for Swinject. 12 | FOUNDATION_EXPORT double SwinjectVersionNumber; 13 | 14 | //! Project version string for Swinject. 15 | FOUNDATION_EXPORT const unsigned char SwinjectVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | -------------------------------------------------------------------------------- /platform_android/navigation/src/main/java/co/joebirch/minimise/navigation/DashboardDirections.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.navigation 2 | 3 | import androidx.navigation.compose.NamedNavArgument 4 | 5 | object DashboardDirections { 6 | 7 | val root = object : NavigationCommand { 8 | 9 | override val arguments = emptyList() 10 | 11 | override val destination = "home" 12 | 13 | } 14 | 15 | val creation = object : NavigationCommand { 16 | 17 | override val arguments = emptyList() 18 | 19 | override val destination = "creation" 20 | 21 | } 22 | } -------------------------------------------------------------------------------- /native/KotlinIOS/Authentication/Authentication.h: -------------------------------------------------------------------------------- 1 | // 2 | // Authentication.h 3 | // Authentication 4 | // 5 | // Created by Joe Birch on 08/01/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for Authentication. 12 | FOUNDATION_EXPORT double AuthenticationVersionNumber; 13 | 14 | //! Project version string for Authentication. 15 | FOUNDATION_EXPORT const unsigned char AuthenticationVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /native/KotlinIOS/Minimise.xcworkspace/xcuserdata/joebirch.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS.xcodeproj/project.xcworkspace/xcuserdata/joebirch.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/remote/AuthenticationRemote.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.remote 2 | 3 | import co.joebirch.minimise.authentication.model.AuthenticationModel 4 | import com.apollographql.apollo.ApolloClient 5 | import com.apollographql.apollo.api.ApolloExperimental 6 | 7 | interface AuthenticationRemote { 8 | 9 | suspend fun signUp( 10 | apiKey: String, 11 | emailAddress: String, 12 | password: String 13 | ): AuthenticationModel 14 | 15 | suspend fun signIn( 16 | apiKey: String, 17 | emailAddress: String, 18 | password: String 19 | ): AuthenticationModel 20 | } -------------------------------------------------------------------------------- /shared/SharedDashboard/src/commonMain/kotlin/co.joebirch.minimise.shared.dashboard/DashboardState.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared.dashboard 2 | 3 | class DashboardState( 4 | val selectedCategory: Category = Category.PendingBelongings, 5 | val pendingBelongings: List = emptyList() 6 | ) { 7 | 8 | fun build(block: Builder.() -> Unit) = Builder(this).apply(block).build() 9 | 10 | class Builder(uiModel: DashboardState) { 11 | var category = uiModel.selectedCategory 12 | var pendingBelongings = uiModel.pendingBelongings 13 | 14 | fun build(): DashboardState { 15 | return DashboardState(category, pendingBelongings) 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /native/KotlinIOS/Dashboard/DashboardViewFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DashboardViewFactory.swift 3 | // Dashboard 4 | // 5 | // Created by Joe Birch on 26/04/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | import Common 12 | 13 | public struct DashboardViewFactory : ViewFactory { 14 | 15 | let viewProvider: ScreenFactory 16 | 17 | public init(viewProvider: ScreenFactory) { 18 | self.viewProvider = viewProvider 19 | } 20 | 21 | public func make() -> AnyView { 22 | let viewModel = DashboardViewModel() 23 | return AnyView(DashboardView(viewModel: viewModel, viewProvider: viewProvider)) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/mapper/ResetPasswordResponseMapper.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.mapper 2 | 3 | import co.joebirch.minimise.authentication.model.ResetPasswordResponse 4 | import co.joebirch.minimise.authentication.model.ResetPasswordResponseModel 5 | 6 | open class ResetPasswordResponseMapper { 7 | 8 | fun mapFromResetPasswordResponse( 9 | resetPasswordResponse: ResetPasswordResponseModel? = null 10 | ) = ResetPasswordResponse( 11 | // resetPasswordResponse.email != null && resetPasswordResponse.code == 200, 12 | //resetPasswordResponse.message, 13 | //resetPasswordResponse.code 14 | ) 15 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/Container.Logging.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | public typealias LoggingFunctionType = (String) -> Void 6 | 7 | public extension Container { 8 | /// Function to be used for logging debugging data. 9 | /// Default implementation writes to standard output. 10 | static var loggingFunction: LoggingFunctionType? { 11 | get { return _loggingFunction } 12 | set { _loggingFunction = newValue } 13 | } 14 | 15 | internal static func log(_ message: String) { 16 | _loggingFunction?(message) 17 | } 18 | } 19 | 20 | private var _loggingFunction: LoggingFunctionType? = { print($0) } 21 | -------------------------------------------------------------------------------- /platform_android/onboarding/src/main/res/layout/fragment_onboarding.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/UnavailableItems.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | // MARK: For auto migration from Swinject v1 to v2. 6 | 7 | extension ObjectScope { 8 | @available(*, unavailable, renamed: "transient") 9 | public static let none = transient 10 | 11 | @available(*, unavailable, renamed: "container") 12 | public static let hierarchy = container 13 | } 14 | 15 | @available(*, unavailable, renamed: "Resolver") 16 | public protocol ResolverType {} 17 | 18 | @available(*, unavailable, renamed: "Assembly") 19 | public protocol AssemblyType {} 20 | 21 | @available(*, unavailable, renamed: "ServiceKeyOption") 22 | public protocol ServiceKeyOptionType {} 23 | -------------------------------------------------------------------------------- /native/KotlinIOS/Dashboard/Dashboard.h: -------------------------------------------------------------------------------- 1 | // 2 | // Dashboard.h 3 | // KotlinIOS 4 | // 5 | // Created by Joe Birch on 02/05/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | // 9 | // Creation.h 10 | // Creation 11 | // 12 | // Created by Joe Birch on 02/05/2020. 13 | // Copyright © 2020 Joe Birch. All rights reserved. 14 | // 15 | 16 | #import 17 | 18 | //! Project version number for Creation. 19 | FOUNDATION_EXPORT double DashboardVersionNumber; 20 | 21 | //! Project version string for Creation. 22 | FOUNDATION_EXPORT const unsigned char DashboardVersionString[]; 23 | 24 | // In this header, you should import all the public headers of your framework using statements like #import 25 | 26 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/RepositoriesProvider.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | import co.joebirch.minimise.authentication.mapper.ResetPasswordResponseMapper 4 | import co.joebirch.minimise.authentication.remote.AuthenticationRemoteStore 5 | import kotlinx.coroutines.ExperimentalCoroutinesApi 6 | 7 | @ExperimentalCoroutinesApi 8 | object RepositoriesProvider { 9 | fun getAuthenticationDataRepository( 10 | remoteStore: AuthenticationRemoteStore, 11 | passwordResponseMapper: ResetPasswordResponseMapper 12 | ): AuthenticationRepository = 13 | AuthenticationDataRepository( 14 | remoteStore, 15 | passwordResponseMapper 16 | ) 17 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/ResetPasswordState.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | import co.joebirch.minimise.shared_common.presentation.UiState 4 | 5 | sealed class ResetPasswordState( 6 | override val isLoading: Boolean = false, 7 | override val success: Boolean = false, 8 | override val errorMessage: String? = null 9 | ): UiState(isLoading, success, errorMessage) { 10 | 11 | object Idle : ResetPasswordState(isLoading = false) 12 | 13 | object Loading : ResetPasswordState(isLoading = true) 14 | 15 | object Success : ResetPasswordState(success = true) 16 | 17 | class Failure(error: String? = null) : 18 | ResetPasswordState(success = false, errorMessage = error) 19 | 20 | } -------------------------------------------------------------------------------- /platform_android/common-ui/src/main/java/co/joebirch/minimise/common_ui/layout.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.common_ui 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Box 5 | import androidx.compose.foundation.shape.RoundedCornerShape 6 | import androidx.compose.material.MaterialTheme 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.ui.Modifier 9 | import androidx.compose.ui.unit.dp 10 | 11 | @Composable 12 | fun RoundedBackgroundBox( 13 | modifier: Modifier = Modifier, 14 | children: @Composable () -> Unit 15 | ) { 16 | Box( 17 | modifier = modifier.background( 18 | MaterialTheme.colors.surface, RoundedCornerShape(16.dp) 19 | ) 20 | ) { 21 | children() 22 | } 23 | } -------------------------------------------------------------------------------- /platform_android/navigation/src/main/res/navigation/dashboard.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 13 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /platform_android/core/build.gradle: -------------------------------------------------------------------------------- 1 | import co.joebirch.minimise.buildsrc.* 2 | 3 | apply plugin: 'com.android.library' 4 | apply plugin: 'kotlin-android' 5 | apply plugin: 'kotlin-android-extensions' 6 | apply plugin: 'kotlin-kapt' 7 | 8 | android { 9 | compileSdkVersion Versions.compileSdk 10 | 11 | defaultConfig { 12 | 13 | minSdkVersion Versions.minSdk 14 | targetSdkVersion Versions.targetSdk 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | } 18 | } 19 | 20 | dependencies { 21 | implementation Deps.AndroidX.appCompat 22 | 23 | implementation Deps.Google.Hilt.hilt 24 | kapt Deps.Google.Hilt.hiltCompiler 25 | 26 | implementation Deps.Kotlin.stdLib 27 | 28 | implementation "androidx.datastore:datastore-preferences:1.0.0-alpha08" 29 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 0.1 19 | CFBundleVersion 20 | 21 21 | 22 | 23 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOSUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 0.1 19 | CFBundleVersion 20 | 21 21 | 22 | 23 | -------------------------------------------------------------------------------- /.github/scripts/create_android_pr_ui_commands.sh: -------------------------------------------------------------------------------- 1 | git fetch --unshallow 2 | git fetch origin 3 | 4 | # Get all the modules that were changed 5 | while read line; do 6 | module_name=${line%%/*} 7 | if [[ ${MODULES} != *"${module_name}"* ]]; then 8 | MODULES="${MODULES} ${module_name}" 9 | fi 10 | done < <(git diff --name-only origin/$GITHUB_BASE_REF) 11 | changed_modules=$MODULES 12 | 13 | # Get a list of all available gradle tasks 14 | AVAILABLE_TASKS=$(./gradlew tasks --all) 15 | 16 | # Check if these modules have gradle tasks 17 | build_commands="" 18 | for module in $changed_modules 19 | do 20 | if [[ $AVAILABLE_TASKS =~ ":platform_android"$module":connectedCheck" ]]; then 21 | build_commands=${build_commands}" "${module}":platform_android:connectedCheck" 22 | fi 23 | done 24 | 25 | echo "./gradlew "${build_commands} 26 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/MinimiseView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MinimiseView.swift 3 | // KotlinIOS 4 | // 5 | // Created by Joe Birch on 26/04/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | import Dashboard 12 | import Authentication 13 | 14 | struct MinimiseView: View { 15 | 16 | var viewProvider: ViewProvider 17 | var authenticated: Bool 18 | 19 | init(authenticated: Bool, viewProvider: ViewProvider) { 20 | self.authenticated = authenticated 21 | self.viewProvider = viewProvider 22 | } 23 | 24 | var body: some View { 25 | if self.authenticated { 26 | return viewProvider.makeDashboardView() 27 | } else { 28 | return viewProvider.makeAuthenticationView() 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /platform_android/design/src/main/res/values-v23/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | 14 | -------------------------------------------------------------------------------- /native/KotlinIOS/DashboardTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /native/KotlinIOS/AuthenticationTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 0.1 19 | CFBundleVersion 20 | 21 21 | 22 | 23 | -------------------------------------------------------------------------------- /platform_android/app/src/main/java/co/joebirch/minimise/android/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.android 2 | 3 | import androidx.hilt.lifecycle.ViewModelInject 4 | import androidx.lifecycle.ViewModel 5 | import co.joebirch.minimise.android.core.di.Preferences 6 | import kotlinx.coroutines.flow.MutableStateFlow 7 | import kotlinx.coroutines.flow.StateFlow 8 | 9 | class MainViewModel @ViewModelInject constructor( 10 | sharedPreferences: Preferences 11 | ) : ViewModel() { 12 | 13 | private val _uiState = MutableStateFlow(MainState.Loading) 14 | val uiState: StateFlow = _uiState 15 | 16 | init { 17 | sharedPreferences.accessToken?.let { 18 | _uiState.value = MainState.Authenticated 19 | } ?: run { 20 | _uiState.value = MainState.NotAuthenticated 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /platform_android/core/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /platform_android/design/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /native/KotlinIOS/Common/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /platform_android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /platform_android/common-ui/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /platform_android/dashboard/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /platform_android/navigation/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /native/KotlinIOS/Creation/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /shared/SharedCreation/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /shared/SharedDashboard/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /native/KotlinIOS/Authentication/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 0.1 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /platform_android/authentication/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle.kts. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/androidTest/java/co/joebirch/minimise/dashboard/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.dashboard 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("co.joebirch.minimise.inventory.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/mapper/AuthenticationResponseMapper.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.mapper 2 | 3 | import co.joebirch.minimise.SignInQuery 4 | import co.joebirch.minimise.SignUpMutation 5 | import co.joebirch.minimise.authentication.model.AuthenticationModel 6 | 7 | fun SignInQuery.Login.toAuthenticationModel(): AuthenticationModel { 8 | return this.asAuthData?.let { 9 | AuthenticationModel(it.token) 10 | } ?: run { 11 | AuthenticationModel(message = this.asAuthenticationError?.message) 12 | } 13 | } 14 | 15 | fun SignUpMutation.CreateUser.toAuthenticationModel(): AuthenticationModel { 16 | return this.asAuthData?.let { 17 | AuthenticationModel(it.token) 18 | } ?: run { 19 | AuthenticationModel(message = this.asAuthenticationError?.message) 20 | } 21 | } -------------------------------------------------------------------------------- /shared/SharedCreation/src/commonMain/kotlin/co.joebirch.minimise.dashboard/CreationStep.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.dashboard 2 | 3 | enum class CreationStep(val position: Int) { 4 | NAME(0), TYPE(1), CATEGORY(2), FREQUENCY(3), POSITIVE(4), 5 | NEGATIVE(5), REMIND(6), FINISHED(7); 6 | 7 | companion object { 8 | fun fromPosition(position: Int): CreationStep { 9 | return when (position) { 10 | 0 -> NAME 11 | 1 -> TYPE 12 | 2 -> CATEGORY 13 | 3 -> FREQUENCY 14 | 4 -> POSITIVE 15 | 5 -> NEGATIVE 16 | 6 -> REMIND 17 | 7 -> FINISHED 18 | else -> throw IllegalArgumentException( 19 | "That position does not translate to a supported step" 20 | ) 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOSTests/KotlinIOSTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import KotlinIOS 3 | 4 | class KotlinIOSTests: XCTestCase { 5 | 6 | override func setUp() { 7 | // Put setup code here. This method is called before the invocation of each test method in the class. 8 | } 9 | 10 | override func tearDown() { 11 | // Put teardown code here. This method is called after the invocation of each test method in the class. 12 | } 13 | 14 | func testExample() { 15 | // This is an example of a functional test case. 16 | // Use XCTAssert and related functions to verify your tests produce the correct results. 17 | } 18 | 19 | func testPerformanceExample() { 20 | // This is an example of a performance test case. 21 | self.measure { 22 | // Put the code you want to measure the time of here. 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /platform_android/creation/src/main/java/co/joebirch/minimise/creation/CreationEvent.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.creation 2 | 3 | import co.joebirch.minimise.dashboard.ItemType 4 | 5 | sealed class CreationEvent { 6 | 7 | data class NameChanged(val name: String) : CreationEvent() 8 | data class ItemTypeChanged(val itemType: ItemType) : CreationEvent() 9 | data class CategoriesChanged(val categories: List) : CreationEvent() 10 | data class FrequencyChanged(val frequency: Float) : CreationEvent() 11 | data class ReminderLengthChanged(val days: Int) : CreationEvent() 12 | data class PositiveNotesChanged(val notes: List) : CreationEvent() 13 | data class NegativeNotesChanged(val notes: List) : CreationEvent() 14 | object NextStepRequested : CreationEvent() 15 | object PreviousStepRequested : CreationEvent() 16 | object FormCompleted : CreationEvent() 17 | 18 | } -------------------------------------------------------------------------------- /native/KotlinIOS/Authentication/AuthenticationViewFactory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthenticationViewFactory.swift 3 | // Authentication 4 | // 5 | // Created by Joe Birch on 26/04/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import SharedAuthentication 11 | import Common 12 | 13 | public struct AuthenticationViewFactory : ViewFactory { 14 | 15 | let backendProvider: Authenticate 16 | let viewProvider: ScreenFactory 17 | 18 | public init(authenticate: Authenticate, 19 | viewProvider: ScreenFactory) { 20 | self.backendProvider = authenticate 21 | self.viewProvider = viewProvider 22 | } 23 | 24 | public func make() -> AnyView { 25 | let viewModel = AuthenticationViewModel(authenticate: backendProvider) 26 | return AnyView(AuthenticationView(viewModel: viewModel, viewProvider: viewProvider)) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /native/KotlinIOS/Dashboard/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BUNDLE_ID 6 | co.joebirch.Minimise 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | 24 | 25 | -------------------------------------------------------------------------------- /native/KotlinIOS/.idea/runConfigurations/Authentication.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/ViewProvider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewProvider.swift 3 | // KotlinIOS 4 | // 5 | // Created by Joe Birch on 26/04/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Swinject 11 | import Dashboard 12 | import Authentication 13 | import Creation 14 | import Common 15 | 16 | class ViewProvider: ObservableObject, ScreenFactory { 17 | 18 | private let resolver: Resolver 19 | 20 | init(resolver: Resolver) { 21 | self.resolver = resolver 22 | } 23 | 24 | func makeDashboardView() -> AnyView { 25 | return self.resolver.resolve(DashboardViewFactory.self)!.make() 26 | } 27 | 28 | func makeAuthenticationView() -> AnyView { 29 | return self.resolver.resolve(AuthenticationViewFactory.self)!.make() 30 | } 31 | 32 | func makeCreationView() -> AnyView { 33 | return self.resolver.resolve(CreationViewFactory.self)!.make() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /native/KotlinIOS/.idea/runConfigurations/KotlinIOS.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /platform_android/core/src/main/java/co/joebirch/minimise/android/core/di/SingleLiveEvent.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.android.core.di 2 | 3 | import androidx.annotation.MainThread 4 | import androidx.lifecycle.LifecycleOwner 5 | import androidx.lifecycle.MutableLiveData 6 | import androidx.lifecycle.Observer 7 | import java.util.concurrent.atomic.AtomicBoolean 8 | 9 | class SingleLiveEvent : MutableLiveData() { 10 | 11 | private val pending = AtomicBoolean(false) 12 | 13 | @MainThread 14 | override fun observe(owner: LifecycleOwner, observer: Observer) { 15 | super.observe(owner, Observer { t -> 16 | if (pending.compareAndSet(true, false)) { 17 | observer.onChanged(t) 18 | } 19 | }) 20 | } 21 | 22 | @MainThread 23 | override fun setValue(t: T?) { 24 | pending.set(true) 25 | super.setValue(t) 26 | } 27 | 28 | @MainThread 29 | fun call() { 30 | value = null 31 | } 32 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Target Support Files/Swinject/Swinject-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.7.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /native/KotlinIOS/.idea/runConfigurations/KotlinIOSTests.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /platform_android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/forgot_password/ForgotPasswordState.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.forgot_password 2 | 3 | class ForgotPasswordState( 4 | val emailAddress: String = "", 5 | val isLoading: Boolean = false, 6 | val success: Boolean? = null, 7 | val errorMessage: String? = null 8 | ) { 9 | 10 | companion object { 11 | fun initialise(): ForgotPasswordState = ForgotPasswordState() 12 | } 13 | 14 | fun build(block: Builder.() -> Unit) = Builder(this).apply(block).build() 15 | 16 | class Builder(state: ForgotPasswordState) { 17 | var userEmail = state.emailAddress 18 | var loading = state.isLoading 19 | var success = state.success 20 | var error = state.errorMessage 21 | 22 | fun build(): ForgotPasswordState { 23 | return ForgotPasswordState( 24 | userEmail, 25 | loading, 26 | success, 27 | error 28 | ) 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /platform_android/design/src/main/res/values/motion.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/Behavior.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | /// Protocol for adding functionality to the container 6 | public protocol Behavior { 7 | /// This will be invoked on each behavior added to the `container` for each `entry` added to the container using 8 | /// one of the `register()` or type forwading methods 9 | /// 10 | /// - Parameters: 11 | /// - container: container into which an `entry` has been registered 12 | /// - type: Type which will be resolved using the `entry` 13 | /// - entry: ServiceEntry registered to the `container` 14 | /// - name: name under which the service has been registered to the `container` 15 | /// 16 | /// - Remark: `Type` and `Service` can be different types in the case of type forwarding 17 | func container( 18 | _ container: Container, 19 | didRegisterType type: Type.Type, 20 | toService entry: ServiceEntry, 21 | withName name: String? 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/Assembly.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | /// The `Assembly` provides a means to organize your `Service` registration in logic groups which allows 6 | /// the user to swap out different implementations of `Services` by providing different `Assembly` instances 7 | /// to the `Assembler` 8 | public protocol Assembly { 9 | /// Provide hook for `Assembler` to load Services into the provided container 10 | /// 11 | /// - parameter container: the container provided by the `Assembler` 12 | /// 13 | func assemble(container: Container) 14 | 15 | /// Provides a hook to the `Assembly` that will be called once the `Assembler` has loaded all `Assembly` 16 | /// instances into the container. 17 | /// 18 | /// - parameter resolver: the resolver that can resolve instances from the built container 19 | /// 20 | func loaded(resolver: Resolver) 21 | } 22 | 23 | public extension Assembly { 24 | func loaded(resolver _: Resolver) { 25 | // no-op 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /native/KotlinIOS/AuthenticationTests/AuthenticationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthenticationTests.swift 3 | // AuthenticationTests 4 | // 5 | // Created by Joe Birch on 08/01/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import Authentication 11 | 12 | class AuthenticationTests: XCTestCase { 13 | 14 | override func setUp() { 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | } 21 | 22 | func testExample() { 23 | // This is an example of a functional test case. 24 | // Use XCTAssert and related functions to verify your tests produce the correct results. 25 | } 26 | 27 | func testPerformanceExample() { 28 | // This is an example of a performance test case. 29 | self.measure { 30 | // Put the code you want to measure the time of here. 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /native/KotlinIOS/DashboardTests/DashboardTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DashboardTests.swift 3 | // DashboardTests 4 | // 5 | // Created by Joe Birch on 23/04/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import Dashboard 11 | 12 | class DashboardTests: XCTestCase { 13 | 14 | override func setUpWithError() throws { 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDownWithError() throws { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | } 21 | 22 | func testExample() throws { 23 | // This is an example of a functional test case. 24 | // Use XCTAssert and related functions to verify your tests produce the correct results. 25 | } 26 | 27 | func testPerformanceExample() throws { 28 | // This is an example of a performance test case. 29 | self.measure { 30 | // Put the code you want to measure the time of here. 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /native/KotlinIOS/AuthenticationTests/AuthenticationViewModelTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AuthenticationViewModelTest.swift 3 | // AuthenticationTests 4 | // 5 | // Created by Joe Birch on 21/03/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SharedAuthentication 11 | @testable import Authentication 12 | 13 | class AuthenticationViewModelTest: XCTestCase { 14 | 15 | var viewModel: AuthenticationViewModel! 16 | 17 | override func setUp() { 18 | super.setUp() 19 | self.viewModel = AuthenticationViewModel(authenticate: nil) 20 | } 21 | 22 | override func tearDown() { } 23 | 24 | func testSetEmailAddressEmitsExpectedEmailState() { 25 | let email = "joe@birch.com" 26 | viewModel.setEmailAddress(emailAddress: email) 27 | XCTAssertTrue(viewModel.state.emailAddress == email) 28 | } 29 | 30 | func testSetPasswordEmitsExpectedPasswordState() { 31 | let password = "my_password" 32 | viewModel.setPassword(password: password) 33 | XCTAssertTrue(viewModel.state.password == password) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /platform_android/common-ui/build.gradle: -------------------------------------------------------------------------------- 1 | import co.joebirch.minimise.buildsrc.* 2 | 3 | apply plugin: 'com.android.library' 4 | apply plugin: 'kotlin-android' 5 | 6 | android { 7 | compileSdkVersion Versions.compileSdk 8 | 9 | defaultConfig { 10 | minSdkVersion Versions.minSdk 11 | } 12 | 13 | compileOptions { 14 | sourceCompatibility JavaVersion.VERSION_1_8 15 | targetCompatibility JavaVersion.VERSION_1_8 16 | } 17 | 18 | buildFeatures { 19 | compose true 20 | } 21 | 22 | kotlinOptions { 23 | jvmTarget = "1.8" 24 | useIR = true 25 | } 26 | 27 | composeOptions { 28 | kotlinCompilerVersion Deps.Kotlin.version 29 | kotlinCompilerExtensionVersion Deps.Compose.version 30 | } 31 | } 32 | 33 | dependencies { 34 | implementation project(":platform_android:design") 35 | 36 | implementation Deps.Compose.material 37 | implementation Deps.Compose.layout 38 | implementation Deps.Compose.foundation 39 | implementation Deps.Compose.runtime 40 | implementation Deps.Compose.tooling 41 | 42 | implementation Deps.Kotlin.stdLib 43 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/util/MockAuthenticationStore.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication.util 2 | 3 | import co.joebirch.minimise.authentication.model.AuthenticationModel 4 | import co.joebirch.minimise.authentication.remote.AuthenticationRemote 5 | 6 | internal class MockAuthenticationStore : AuthenticationRemote { 7 | 8 | lateinit var whenSignUp: ( 9 | email: String, 10 | password: String 11 | ) -> AuthenticationModel 12 | 13 | lateinit var whenSignIn: ( 14 | email: String, 15 | password: String 16 | ) -> AuthenticationModel 17 | 18 | override suspend fun signUp( 19 | apiKey: String, 20 | email: String, 21 | password: String 22 | ) = whenSignUp(email, password) 23 | 24 | override suspend fun signIn( 25 | apiKey: String, 26 | email: String, 27 | password: String 28 | ) = whenSignIn(email, password) 29 | 30 | override fun resetPassword( 31 | apiKey: String, 32 | emailAddress: String) { 33 | TODO("Not yet implemented") 34 | } 35 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOSUITests/KotlinIOSUITests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | class KotlinIOSUITests: XCTestCase { 4 | 5 | override func setUp() { 6 | // Put setup code here. This method is called before the invocation of each test method in the class. 7 | 8 | // In UI tests it is usually best to stop immediately when a failure occurs. 9 | continueAfterFailure = false 10 | 11 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 12 | XCUIApplication().launch() 13 | 14 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 15 | } 16 | 17 | override func tearDown() { 18 | // Put teardown code here. This method is called after the invocation of each test method in the class. 19 | } 20 | 21 | func testExample() { 22 | // Use recording to get started writing UI tests. 23 | // Use XCTAssert and related functions to verify your tests produce the correct results. 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /.github/secrets/decrypt_secrets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eo pipefail 3 | 4 | gpg --quiet --batch --yes --decrypt --pinentry-mode loopback --passphrase="$IOS_KEYS" --output ./.github/secrets/github_actions.mobileprovision.mobileprovision ./.github/secrets/github_actions.mobileprovision.gpg 5 | gpg --quiet --batch --yes --decrypt --pinentry-mode loopback --passphrase="$IOS_KEYS" --output ./.github/secrets/Certificates.p12 ./.github/secrets/Certificates.p12.gpg 6 | 7 | mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles 8 | 9 | cp ./.github/secrets/github_actions.mobileprovision.mobileprovision ~/Library/MobileDevice/Provisioning\ Profiles/github_actions.mobileprovision.mobileprovision 10 | 11 | 12 | security create-keychain -p "" build.keychain 13 | security import ./.github/secrets/Certificates.p12 -t agg -k ~/Library/Keychains/build.keychain -P "$IOS_KEYS" -A 14 | 15 | security list-keychains -s ~/Library/Keychains/build.keychain 16 | security default-keychain -s ~/Library/Keychains/build.keychain 17 | security unlock-keychain -p "" ~/Library/Keychains/build.keychain 18 | 19 | security set-key-partition-list -S apple-tool:,apple: -s -k "" ~/Library/Keychains/build.keychain 20 | -------------------------------------------------------------------------------- /platform_android/authentication/src/main/res/navigation/forgot_password_nav.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 15 | 16 | 17 | 20 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /platform_android/authentication/src/test/java/co/joebirch/minimise/authentication/AuthenticationValidatorTest.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | import co.joebirch.minimise.authentication.util.AuthenticationValidator 4 | import org.junit.Test 5 | 6 | import org.junit.Assert.* 7 | 8 | class AuthenticationValidatorTest { 9 | 10 | private val authenticationValidator = 11 | AuthenticationValidator() 12 | 13 | @Test 14 | fun `Input data returns as valid`() { 15 | assertTrue(authenticationValidator.validateInputData("password", 16 | "someemail@email.com")) 17 | } 18 | 19 | @Test 20 | fun `Input data returns as invalid when password empty`() { 21 | assertFalse(authenticationValidator.validateInputData("", 22 | "someemail@email.com")) 23 | } 24 | 25 | @Test 26 | fun `Input data returns as invalid when email empty`() { 27 | assertFalse(authenticationValidator.validateInputData("password", "")) 28 | } 29 | 30 | @Test 31 | fun `Input data returns as invalid when email and password empty`() { 32 | assertFalse(authenticationValidator.validateInputData("", "")) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Swinject Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/_Resolver.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | /// This protocol is designed for the use to extend Swinject functionality. 6 | /// Do NOT use this protocol unless you intend to write an extension or plugin to Swinject framework. 7 | /// 8 | /// A type conforming Resolver protocol must conform _Resolver protocol too. 9 | public protocol _Resolver { 10 | /// This method is designed for the use to extend Swinject functionality. 11 | /// Do NOT use this method unless you intend to write an extension or plugin to Swinject framework. 12 | /// 13 | /// - Parameter name: The registration name. 14 | /// - Parameter option: A service key option for an extension/plugin. 15 | /// - Parameter invoker: A closure to execute service resolution. 16 | /// 17 | /// - Returns: The resolved service type instance, or nil if no service is found. 18 | // swiftlint:disable:next identifier_name 19 | func _resolve( 20 | name: String?, 21 | option: ServiceKeyOption?, 22 | invoker: @escaping ((Arguments) -> Any) -> Any 23 | ) -> Service? 24 | } 25 | -------------------------------------------------------------------------------- /platform_android/authentication/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Sign Up 4 | Sign In 5 | Already have an account? 6 | Don\'t have an account yet? 7 | Forgotten your password? 8 | 9 | Sign in to your Minimise account 10 | Sign up for a Minimise account 11 | 12 | Email Address 13 | Password 14 | Whoops 15 | There was a problem performing that request. Please try again! 16 | OK 17 | 18 | 19 | Email Address 20 | Reset password 21 | Rest Password 22 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable/ic_four.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | 24 | 30 | 31 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS.xctestplan: -------------------------------------------------------------------------------- 1 | { 2 | "configurations" : [ 3 | { 4 | "id" : "C5ADB152-C64A-414A-A7DB-BCA99D5DDFE4", 5 | "name" : "Configuration 1", 6 | "options" : { 7 | 8 | } 9 | } 10 | ], 11 | "defaultOptions" : { 12 | "codeCoverage" : false, 13 | "targetForVariableExpansion" : { 14 | "containerPath" : "container:KotlinIOS.xcodeproj", 15 | "identifier" : "47729E0122F447C800B9B36B", 16 | "name" : "KotlinIOS" 17 | } 18 | }, 19 | "testTargets" : [ 20 | { 21 | "target" : { 22 | "containerPath" : "container:KotlinIOS.xcodeproj", 23 | "identifier" : "47729E1522F447CA00B9B36B", 24 | "name" : "KotlinIOSTests" 25 | } 26 | }, 27 | { 28 | "target" : { 29 | "containerPath" : "container:KotlinIOS.xcodeproj", 30 | "identifier" : "47729E2022F447CA00B9B36B", 31 | "name" : "KotlinIOSUITests" 32 | } 33 | }, 34 | { 35 | "target" : { 36 | "containerPath" : "container:KotlinIOS.xcodeproj", 37 | "identifier" : "426F9AE923C6437C00A8437A", 38 | "name" : "AuthenticationTests" 39 | } 40 | } 41 | ], 42 | "version" : 1 43 | } 44 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/util/AuthenticationResponseFactory.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication.util 2 | 3 | import co.joebirch.minimise.authentication.model.AuthenticationModel 4 | import co.joebirch.minimise.shared_authentication.util.DataFactory.randomInt 5 | import co.joebirch.minimise.shared_authentication.util.DataFactory.randomString 6 | 7 | object AuthenticationResponseFactory { 8 | 9 | fun makeAuthenticationModel() = 10 | AuthenticationModel( 11 | randomString() 12 | ) 13 | 14 | fun makeAuthenticationResponse(token: String = randomString()) = 15 | AuthenticationModel(token, randomString(), randomInt()) 16 | 17 | fun makeAuthenticationModelForError() = 18 | AuthenticationModel( 19 | null, 20 | message = randomString(), 21 | errorCode = randomInt() 22 | ) 23 | 24 | fun makeAuthenticationResponseForError( 25 | message: String = randomString(), 26 | errorCode: Int = randomInt() 27 | ) = AuthenticationModel( 28 | null, 29 | message = message, 30 | errorCode = errorCode 31 | ) 32 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/AuthenticationRepository.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | import co.joebirch.minimise.authentication.mapper.ResetPasswordResponseMapper 4 | import co.joebirch.minimise.authentication.model.AuthenticationModel 5 | import co.joebirch.minimise.authentication.model.ResetPasswordResponse 6 | import co.joebirch.minimise.authentication.remote.AuthenticationRemoteStore 7 | 8 | interface AuthenticationRepository { 9 | 10 | suspend fun signUp( 11 | apiKey: String, 12 | emailAddress: String, 13 | password: String 14 | ): AuthenticationModel 15 | 16 | suspend fun signIn( 17 | apiKey: String, 18 | emailAddress: String, 19 | password: String 20 | ): AuthenticationModel 21 | 22 | suspend fun resetPassword( 23 | apiKey: String, 24 | emailAddress: String 25 | ): ResetPasswordResponse 26 | 27 | companion object { 28 | fun create(): AuthenticationRepository = 29 | RepositoriesProvider.getAuthenticationDataRepository( 30 | AuthenticationRemoteStore(), 31 | ResetPasswordResponseMapper() 32 | ) 33 | } 34 | } -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable/ic_menu.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | 24 | 30 | 31 | -------------------------------------------------------------------------------- /platform_android/navigation/src/main/java/co/joebirch/minimise/navigation/AuthenticationDirections.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.navigation 2 | 3 | import androidx.navigation.compose.NamedNavArgument 4 | 5 | object AuthenticationDirections { 6 | 7 | val root = object : NavigationCommand { 8 | 9 | override val arguments = emptyList() 10 | 11 | override val destination = "connect" 12 | 13 | } 14 | 15 | val authentication = object : NavigationCommand { 16 | 17 | override val arguments = emptyList() 18 | 19 | override val destination = "authentication" 20 | 21 | } 22 | 23 | val Default = object : NavigationCommand { 24 | 25 | override val arguments = emptyList() 26 | 27 | override val destination = "" 28 | 29 | } 30 | 31 | val dashboard = object : NavigationCommand { 32 | 33 | override val arguments = emptyList() 34 | 35 | override val destination = "dashboard" 36 | } 37 | 38 | val forgotPassword = object : NavigationCommand { 39 | 40 | override val arguments = emptyList() 41 | 42 | override val destination = "forgot_password" 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable/ic_two.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | 24 | 25 | -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable/ic_three.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | 24 | 25 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/SynchronizedResolver.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | internal final class SynchronizedResolver { 6 | internal let container: Container 7 | 8 | internal init(container: Container) { 9 | self.container = container 10 | } 11 | } 12 | 13 | extension SynchronizedResolver: _Resolver { 14 | // swiftlint:disable:next identifier_name 15 | internal func _resolve( 16 | name: String?, 17 | option: ServiceKeyOption?, 18 | invoker: @escaping ((Arguments) -> Any) -> Any 19 | ) -> Service? { 20 | return container.lock.sync { 21 | self.container._resolve(name: name, option: option, invoker: invoker) 22 | } 23 | } 24 | } 25 | 26 | extension SynchronizedResolver: Resolver { 27 | internal func resolve(_ serviceType: Service.Type) -> Service? { 28 | return container.lock.sync { 29 | self.container.resolve(serviceType) 30 | } 31 | } 32 | 33 | internal func resolve(_ serviceType: Service.Type, name: String?) -> Service? { 34 | return container.lock.sync { 35 | self.container.resolve(serviceType, name: name) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/MockAuthenticationDataRepository.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | import co.joebirch.minimise.authentication.AuthenticationRepository 4 | import co.joebirch.minimise.authentication.model.AuthenticationModel 5 | import co.joebirch.minimise.authentication.model.ResetPasswordResponse 6 | 7 | internal class MockAuthenticationDataRepository : 8 | AuthenticationRepository { 9 | 10 | lateinit var whenSignUp: (email: String, password: String) -> AuthenticationModel 11 | lateinit var whenSignIn: (email: String, password: String) -> AuthenticationModel 12 | lateinit var whenResetPassword: (apiKey: String, emailAddress: String) -> ResetPasswordResponse 13 | 14 | override suspend fun signUp( 15 | apiKey: String, 16 | emailAddress: String, 17 | password: String 18 | ) = whenSignUp(emailAddress, password) 19 | 20 | override suspend fun signIn( 21 | apiKey: String, 22 | emailAddress: String, 23 | password: String 24 | ) = whenSignIn(emailAddress, password) 25 | 26 | override suspend fun resetPassword( 27 | apiKey: String, 28 | emailAddress: String 29 | ) = whenResetPassword(apiKey, emailAddress) 30 | } -------------------------------------------------------------------------------- /native/KotlinIOS/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :ios, '13.0' 3 | 4 | use_frameworks! 5 | 6 | target 'Authentication' do 7 | # Comment the next line if you don't want to use dynamic frameworks 8 | inherit! :search_paths 9 | # Pods for Authentication 10 | pod 'SharedAuthentication', :path => '../../shared/SharedAuthentication' 11 | 12 | target 'AuthenticationTests' do 13 | # Pods for testing 14 | 15 | end 16 | 17 | end 18 | 19 | 20 | target 'Dashboard' do 21 | # Comment the next line if you don't want to use dynamic frameworks 22 | inherit! :search_paths 23 | # Pods for Authentication 24 | target 'DashboardTests' do 25 | # Pods for testing 26 | 27 | end 28 | 29 | end 30 | 31 | target 'Creation' do 32 | # Comment the next line if you don't want to use dynamic frameworks 33 | inherit! :search_paths 34 | # Pods for Authentication 35 | 36 | end 37 | 38 | target 'KotlinIOS' do 39 | # Comment the next line if you don't want to use dynamic frameworks 40 | inherit! :search_paths 41 | # Pods for KotlinIOS 42 | pod 'Swinject' 43 | target 'KotlinIOSTests' do 44 | inherit! :search_paths 45 | # Pods for testing 46 | end 47 | 48 | target 'KotlinIOSUITests' do 49 | # Pods for testing 50 | end 51 | 52 | end 53 | -------------------------------------------------------------------------------- /platform_android/design/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 17 | 18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/AuthenticationDataRepository.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | import co.joebirch.minimise.authentication.mapper.ResetPasswordResponseMapper 4 | import co.joebirch.minimise.authentication.model.ResetPasswordResponse 5 | import co.joebirch.minimise.authentication.remote.AuthenticationRemote 6 | 7 | class AuthenticationDataRepository constructor( 8 | private val authenticationStore: AuthenticationRemote, 9 | private val resetPasswordResponseMapper: ResetPasswordResponseMapper 10 | ) : AuthenticationRepository { 11 | 12 | override suspend fun signUp( 13 | apiKey: String, 14 | emailAddress: String, 15 | password: String 16 | ) = authenticationStore.signUp(apiKey, emailAddress, password) 17 | 18 | override suspend fun signIn( 19 | apiKey: String, 20 | emailAddress: String, 21 | password: String 22 | ) = authenticationStore.signIn(apiKey, emailAddress, password) 23 | 24 | override suspend fun resetPassword( 25 | apiKey: String, 26 | emailAddress: String 27 | ): ResetPasswordResponse { 28 | return resetPasswordResponseMapper.mapFromResetPasswordResponse( 29 | //authenticationStore.resetPassword(apiKey, emailAddress) 30 | ) 31 | } 32 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/ObjectScope.Standard.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | extension ObjectScope { 6 | /// A new instance is always created by the `Container` when a type is resolved. 7 | /// The instance is not shared. 8 | public static let transient = ObjectScope(storageFactory: TransientStorage.init, description: "transient") 9 | 10 | /// Instances are shared only when an object graph is being created, 11 | /// otherwise a new instance is created by the `Container`. This is the default scope. 12 | public static let graph = ObjectScope(storageFactory: GraphStorage.init, description: "graph") 13 | 14 | /// An instance provided by the `Container` is shared within the `Container` and its child `Containers`. 15 | public static let container = ObjectScope(storageFactory: PermanentStorage.init, description: "container") 16 | 17 | /// An instance provided by the `Container` is shared within the `Container` and its child `Container`s 18 | /// as long as there are strong references to given instance. Otherwise new instance is created 19 | /// when resolving the type. 20 | public static let weak = ObjectScope(storageFactory: WeakStorage.init, description: "weak", 21 | parent: ObjectScope.graph) 22 | } 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minimise 2 | 3 | Minimise app built using kotlin multiplatform 4 | 5 | ![CI](https://github.com/hitherejoe/minimise/workflows/CI/badge.svg?branch=master) 6 | 7 | Minimise is an app for Android & iOS. It's purpose is to help us think more about the purchases we make and rediscover the things that we own. 8 | 9 | Minimise is currently under heavy development and is not open to outside contributions. Once things are more buil out, this will change! 10 | 11 | [Android App source code](https://github.com/hitherejoe/minimise/tree/master/platform_android) 12 | 13 | [iOS App source code](https://github.com/hitherejoe/minimise/tree/master/native/KotlinIOS) 14 | 15 | [Shared Multiplatform code](https://github.com/hitherejoe/minimise/tree/master/shared) 16 | 17 | 18 | ## Android App 19 | 20 | 21 | ### Creation 22 | 23 | ![Creation flow](art/screenshots.png) 24 | 25 | 26 | ## Supporting blog posts 27 | 28 | [Building an App with Kotlin Multiplatform: Structuring our app 29 | ](https://joebirch.co/2020/01/16/building-an-app-with-kotlin-multiplatform-structuring-our-app/) 30 | 31 | [Building our Authentication Module](https://joebirch.co/2020/03/19/building-an-app-with-kotlin-multiplatform-building-our-authentication-module/) 32 | 33 | 34 | ## Contributions 35 | 36 | The project is current changing a lot, so currently I'm not accepting external contributions :) 37 | -------------------------------------------------------------------------------- /platform_android/core/src/main/java/co/joebirch/minimise/android/core/di/Preferences.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.android.core.di 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import androidx.datastore.core.DataStore 6 | import androidx.datastore.preferences.core.Preferences 7 | import androidx.datastore.preferences.core.edit 8 | import androidx.datastore.preferences.core.stringPreferencesKey 9 | import androidx.datastore.preferences.preferencesDataStore 10 | import dagger.hilt.android.qualifiers.ApplicationContext 11 | import kotlinx.coroutines.flow.Flow 12 | import kotlinx.coroutines.flow.map 13 | import javax.inject.Inject 14 | 15 | class Preferences @Inject constructor( 16 | @ApplicationContext val context: Context 17 | ) { 18 | 19 | val Context.dataStore: DataStore by preferencesDataStore(name = "settings") 20 | val KEY_AUTH_TOKEN = stringPreferencesKey("auth_token") 21 | val accessToken: Flow = context.dataStore.data 22 | .map { preferences -> 23 | preferences[KEY_AUTH_TOKEN] 24 | } 25 | 26 | suspend fun setAuthToken(token: String) { 27 | context.dataStore.edit { settings -> 28 | settings[KEY_AUTH_TOKEN] = token 29 | } 30 | } 31 | 32 | companion object { 33 | const val KEY_AUTH_TOKEN = "KEY_AUTH_TOKEN" 34 | } 35 | } -------------------------------------------------------------------------------- /platform_android/dashboard/src/main/res/drawable/ic_one.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | 24 | 30 | 31 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/Container.TypeForwarding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | extension Container { 6 | /// Adds the registration for `type` which resolves in the same way, as would the type 7 | /// used to create the original `service` - i.e. using the same object scope, 8 | /// arguments and `initCompleted` closures. 9 | /// 10 | /// ** Example usage ** 11 | /// 12 | /// let service = container.register(Dog.self) { _ in Dog() } 13 | /// container.forward(Animal.self, to: service) 14 | /// 15 | /// let dogAsAnimal = container.resolve(Animal.self) 16 | /// 17 | /// - Parameters: 18 | /// - type: Type resolution of which should be forwarded 19 | /// - name: A registration name, which is used to differentiate from other registrations of the same `type` 20 | /// - service: ServiceEntry which should be used for resolution of `type` 21 | public func forward(_ type: T.Type, name: String? = nil, to service: ServiceEntry) { 22 | let key = ServiceKey( 23 | serviceType: T.self, 24 | argumentsType: service.argumentsType, 25 | name: name, 26 | option: nil 27 | ) 28 | services[key] = service 29 | behaviors.forEach { $0.container(self, didRegisterType: type, toService: service, withName: name) } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /shared/SharedCreation/src/commonMain/kotlin/co.joebirch.minimise.dashboard/CreationState.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.dashboard 2 | 3 | class CreationState( 4 | val currentStep: CreationStep = CreationStep.NAME, 5 | val isLoading: Boolean = false, 6 | val name: String = "", 7 | val categories: List = emptyList(), 8 | val frequencyCount: Float = 0f, 9 | val positiveReasons: List = emptyList(), 10 | val negativeReasons: List = emptyList(), 11 | val daysToRemind: Int = 2, 12 | val itemType: ItemType? = null 13 | ) { 14 | 15 | fun build(block: Builder.() -> Unit) = Builder(this).apply(block).build() 16 | 17 | class Builder(uiModel: CreationState) { 18 | private val currentState = uiModel 19 | var creationStep = currentState.currentStep 20 | var isLoading = currentState.isLoading 21 | var name = currentState.name 22 | var categories = currentState.categories 23 | var frequency = currentState.frequencyCount 24 | var positiveReasons = currentState.positiveReasons 25 | var negativeReasons = currentState.negativeReasons 26 | var daysToRemind = currentState.daysToRemind 27 | var itemType = currentState.itemType 28 | 29 | fun build() = CreationState( 30 | creationStep, isLoading, name, categories, 31 | frequency, positiveReasons, negativeReasons, daysToRemind, 32 | itemType 33 | ) 34 | } 35 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | 21 | # Kotlin code style for this project: "official" or "obsolete": 22 | kotlin.code.style=official 23 | kotlin.mpp.enableGranularSourceSetsMetadata=true 24 | android.enableGradleWorkers=true 25 | kapt.use.worker.api=true 26 | kapt.incremental.apt=true 27 | kapt.include.compile.classpath=false 28 | org.gradle.configureondemand=false 29 | org.gradle.caching=true 30 | org.gradle.parallel=true -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/DependencyAssembler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Assembler.swift 3 | // KotlinIOS 4 | // 5 | // Created by Joe Birch on 26/04/2020. 6 | // Copyright © 2020 Joe Birch. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | import Authentication 12 | import SharedAuthentication 13 | import Dashboard 14 | import Swinject 15 | import Common 16 | import Creation 17 | 18 | class DependencyAssembler: Assembly { 19 | 20 | func assemble(container: Container) { 21 | container.register(Authenticate.self) { _ in Authenticate() } 22 | .inObjectScope(.container) 23 | 24 | container.register(ScreenFactory.self) { resolver -> ScreenFactory in 25 | ViewProvider( 26 | resolver: container 27 | ) 28 | } 29 | 30 | container.register(DashboardViewFactory.self) { resolver -> DashboardViewFactory in 31 | DashboardViewFactory(viewProvider: container.resolve(ScreenFactory.self)! 32 | ) 33 | } 34 | 35 | container.register(AuthenticationViewFactory.self) { resolver -> AuthenticationViewFactory in 36 | AuthenticationViewFactory( 37 | authenticate: container.resolve(Authenticate.self)!, viewProvider: container.resolve(ScreenFactory.self)! 38 | ) 39 | } 40 | 41 | container.register(CreationViewFactory.self) { resolver -> CreationViewFactory in 42 | CreationViewFactory() 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /platform_android/common-ui/src/main/java/co/joebirch/minimise/common_ui/theme.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.common_ui 2 | 3 | import androidx.compose.foundation.isSystemInDarkTheme 4 | import androidx.compose.material.MaterialTheme 5 | import androidx.compose.material.lightColors 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.graphics.Color 8 | import androidx.compose.ui.res.colorResource 9 | 10 | @Composable 11 | fun MinimiseTheme( 12 | darkTheme: Boolean = isSystemInDarkTheme(), 13 | content: @Composable() () -> Unit 14 | ) { 15 | MaterialTheme( 16 | colors = lightColors( 17 | primary = colorResource(id = R.color.primaryColor), 18 | primaryVariant = colorResource(id = R.color.primaryDarkColor), 19 | onPrimary = colorResource(id = R.color.color_on_primary), 20 | secondary = colorResource(id = R.color.secondaryColor), 21 | secondaryVariant = colorResource(id = R.color.secondaryDarkColor), 22 | onSecondary = colorResource(id = R.color.color_on_secondary), 23 | error = colorResource(id = R.color.color_error), 24 | surface = colorResource(id = R.color.color_surface), 25 | onSurface = colorResource(id = R.color.color_on_surface), 26 | background = colorResource(id = R.color.color_background), 27 | onBackground = colorResource(id = R.color.color_on_background) 28 | ), 29 | content = content, 30 | typography = themeTypography 31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/android-pr-workflow.yml: -------------------------------------------------------------------------------- 1 | name: Run checks for Android module changes 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'platform_android/**' 7 | 8 | jobs: 9 | test: 10 | runs-on: macos-latest 11 | steps: 12 | - name: checkout 13 | uses: actions/checkout@v2 14 | - name: set up JDK 1.8 15 | uses: actions/setup-java@v1 16 | with: 17 | java-version: 1.8 18 | - name: Create UI test commands 19 | run: | 20 | git fetch origin 21 | 22 | while read line; do 23 | tmp=${line#*/} 24 | module_name=${tmp%%/*} 25 | if [[ ${MODULES} != *"${module_name}"* ]]; then 26 | MODULES="${MODULES} ${module_name}" 27 | fi 28 | done < <(git diff --name-only origin/$GITHUB_BASE_REF) 29 | changed_modules=$MODULES 30 | 31 | AVAILABLE_TASKS=$(./gradlew tasks --all) 32 | dest="origin/"${{ github.base_ref }} 33 | branch="origin/"${{ github.head_ref }} 34 | build_commands="" 35 | for module in $changed_modules 36 | do 37 | if [[ ${module} != ".github" && ${module} != "buildSrc" && $AVAILABLE_TASKS == *"platform_android:${module}:connectedCheck"* ]]; then 38 | build_commands="${build_commands} platform_android:${module}:connectedCheck" 39 | fi 40 | done 41 | - name: run tests 42 | uses: reactivecircus/android-emulator-runner@v2.11.0 43 | with: 44 | api-level: 29 45 | script: | 46 | ./gradlew ${{ env.COMMANDS }} 47 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/AuthenticationState.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | class AuthenticationState( 4 | val emailAddress: String = "", 5 | val password: String = "", 6 | val isAuthenticationContentValid: Boolean = false, 7 | val authenticationMode: AuthenticateMode = AuthenticateMode.SignUp, 8 | val isLoading: Boolean = false, 9 | val success: Boolean? = null, 10 | val errorMessage: String? = null 11 | ) { 12 | 13 | companion object { 14 | fun initialise(): AuthenticationState = AuthenticationState() 15 | } 16 | 17 | fun build(block: Builder.() -> Unit) = Builder(this).apply(block).build() 18 | 19 | class Builder(state: AuthenticationState) { 20 | var userEmail = state.emailAddress 21 | var userPassword = state.password 22 | var isAuthenticationContentValid = userEmail.trim().isNotEmpty() && 23 | userPassword.trim().isNotEmpty() 24 | var mode: AuthenticateMode = state.authenticationMode 25 | var loading = state.isLoading 26 | var success = state.success 27 | var error = state.errorMessage 28 | 29 | fun build(): AuthenticationState { 30 | return AuthenticationState( 31 | userEmail, 32 | userPassword, 33 | isAuthenticationContentValid, 34 | mode, 35 | loading, 36 | success, 37 | error 38 | ) 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /platform_android/creation/src/test/java/co/joebirch/minimise/creation/util.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.creation 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.Observer 5 | 6 | /** 7 | * Represents a list of capture values from a LiveData. 8 | */ 9 | class LiveDataValueCapture { 10 | 11 | val lock = Any() 12 | 13 | private val _values = mutableListOf() 14 | val values: List 15 | get() = synchronized(lock) { 16 | _values.toList() // copy to avoid returning reference to mutable list 17 | } 18 | 19 | fun addValue(value: T?) = synchronized(lock) { 20 | _values += value 21 | } 22 | } 23 | 24 | /** 25 | * Extension function to capture all values that are emitted to a LiveData during the execution of 26 | * `captureBlock`. 27 | * 28 | * @param captureBlock a lambda that will 29 | */ 30 | inline fun LiveData.captureValues(block: LiveDataValueCapture.() -> Unit) { 31 | val capture = LiveDataValueCapture() 32 | val observer = Observer { 33 | capture.addValue(it) 34 | } 35 | observeForever(observer) 36 | try { 37 | capture.block() 38 | } finally { 39 | removeObserver(observer) 40 | } 41 | } 42 | 43 | /** 44 | * Get the current value from a LiveData without needing to register an observer. 45 | */ 46 | fun LiveData.getValueForTest(): T? { 47 | var value: T? = null 48 | var observer = Observer { 49 | value = it 50 | } 51 | observeForever(observer) 52 | removeObserver(observer) 53 | return value 54 | } 55 | -------------------------------------------------------------------------------- /platform_android/onboarding/build.gradle: -------------------------------------------------------------------------------- 1 | import co.joebirch.minimise.buildsrc.* 2 | 3 | apply plugin: "com.android.library" 4 | apply plugin: 'kotlin-android' 5 | apply plugin: 'kotlin-android-extensions' 6 | apply plugin: 'kotlin-kapt' 7 | apply plugin: 'dagger.hilt.android.plugin' 8 | 9 | android { 10 | compileSdkVersion Versions.compileSdk 11 | 12 | viewBinding { 13 | enabled = true 14 | } 15 | 16 | defaultConfig { 17 | minSdkVersion Versions.minSdk 18 | targetSdkVersion Versions.targetSdk 19 | 20 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 21 | } 22 | 23 | compileOptions { 24 | sourceCompatibility JavaVersion.VERSION_1_8 25 | targetCompatibility JavaVersion.VERSION_1_8 26 | } 27 | 28 | kotlinOptions { 29 | jvmTarget = "1.8" 30 | } 31 | } 32 | 33 | dependencies { 34 | 35 | implementation project(":platform_android:navigation") 36 | implementation project(":platform_android:core") 37 | implementation Deps.Google.material 38 | implementation Deps.AndroidX.coreKtx 39 | implementation Deps.Fragment.base 40 | implementation Deps.AndroidX.appCompat 41 | 42 | implementation Deps.Google.Hilt.hilt 43 | implementation Deps.Google.Hilt.viewmodel 44 | kapt Deps.Google.Hilt.hiltCompiler 45 | 46 | implementation Deps.Lifecycle.viewModelKtx 47 | 48 | testImplementation Deps.junit 49 | 50 | androidTestImplementation Deps.AndroidX.annotation 51 | androidTestImplementation Deps.AndroidX.junit 52 | androidTestImplementation Deps.Espresso.core 53 | } 54 | -------------------------------------------------------------------------------- /shared/SharedCommon/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget 2 | import co.joebirch.minimise.buildsrc.Deps 3 | import co.joebirch.minimise.buildsrc.Versions 4 | 5 | plugins { 6 | kotlin("multiplatform") 7 | id("kotlinx-serialization") 8 | id("org.jetbrains.kotlin.native.cocoapods") 9 | } 10 | 11 | kotlin { 12 | val iOSTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget = 13 | if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true) 14 | ::iosArm64 15 | else 16 | ::iosX64 17 | jvm("android") 18 | 19 | iOSTarget("ios") { 20 | binaries { 21 | framework("SharedAuthentication") { 22 | baseName = "SharedAuthentication" 23 | } 24 | } 25 | } 26 | 27 | sourceSets { 28 | val commonMain by getting { 29 | dependencies { 30 | implementation(Deps.Kotlin.common) 31 | 32 | } 33 | } 34 | 35 | val mobileMain by creating { 36 | dependsOn(commonMain) 37 | } 38 | 39 | val androidMain by getting { 40 | dependsOn(mobileMain) 41 | dependencies { 42 | implementation(Deps.Kotlin.stdLib) 43 | implementation(Deps.Coroutines.android) 44 | implementation(Deps.Coroutines.core) 45 | } 46 | } 47 | 48 | val iosMain by getting { 49 | dependsOn(mobileMain) 50 | dependencies { 51 | 52 | //api(Deps.Coroutines.iOSarm64) 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Swinject 3 | import Dashboard 4 | 5 | @UIApplicationMain 6 | class AppDelegate: UIResponder, UIApplicationDelegate { 7 | 8 | 9 | func application(_ application: UIApplication, didFinishLaunchingWithOptions 10 | launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 11 | // [START firebase_configure] 12 | 13 | return true 14 | } 15 | 16 | func applicationWillTerminate(_ application: UIApplication) { 17 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 18 | } 19 | 20 | // MARK: UISceneSession Lifecycle 21 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 22 | // Called when a new scene session is being created. 23 | // Use this method to select a configuration to create the new scene with. 24 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 25 | } 26 | 27 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 28 | // Called when the user discards a scene session. 29 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 30 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /platform_android/authentication/src/main/kotlin/co/joebirch/minimise/authentication/AuthenticationModule.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication 2 | 3 | import co.joebirch.minimise.authentication.interactor.Authenticate 4 | import co.joebirch.minimise.authentication.interactor.ResetPassword 5 | import co.joebirch.minimise.authentication.mapper.ResetPasswordResponseMapper 6 | import co.joebirch.minimise.authentication.remote.AuthenticationRemote 7 | import co.joebirch.minimise.authentication.remote.AuthenticationRemoteStore 8 | import dagger.Module 9 | import dagger.Provides 10 | import dagger.hilt.InstallIn 11 | import dagger.hilt.android.components.ActivityComponent 12 | import dagger.hilt.android.components.ViewModelComponent 13 | 14 | @Module 15 | @InstallIn(ViewModelComponent::class) 16 | object AuthenticationModule { 17 | 18 | @Provides 19 | fun providesAuthenticate( 20 | repository: AuthenticationRepository 21 | ): Authenticate = Authenticate(repository) 22 | 23 | @Provides 24 | fun providesResetPassword( 25 | repository: AuthenticationRepository 26 | ): ResetPassword = ResetPassword(repository) 27 | 28 | @Provides 29 | fun providesResetPasswordResponseMapper() = 30 | ResetPasswordResponseMapper() 31 | 32 | @Provides 33 | fun providesAuthenticationRepository( 34 | repository: AuthenticationRemote, 35 | resetPasswordResponseMapper: ResetPasswordResponseMapper 36 | ): AuthenticationRepository = AuthenticationDataRepository(repository, 37 | resetPasswordResponseMapper) 38 | 39 | @Provides 40 | fun providesAuthenticationRemote(): AuthenticationRemote = AuthenticationRemoteStore() 41 | } -------------------------------------------------------------------------------- /platform_android/authentication/src/main/kotlin/co/joebirch/minimise/authentication/reset_password/ResetPasswordViewModel.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.reset_password 2 | 3 | import androidx.lifecycle.* 4 | import co.joebirch.minimise.android.core.di.BaseViewModel 5 | import co.joebirch.minimise.android.core.di.default 6 | import co.joebirch.minimise.authentication.interactor.ResetPassword 7 | import co.joebirch.minimise.authentication.ResetPasswordView 8 | import co.joebirch.minimise.authentication.forgot_password.ForgotPasswordState 9 | import dagger.hilt.android.lifecycle.HiltViewModel 10 | import kotlinx.coroutines.flow.MutableStateFlow 11 | import kotlinx.coroutines.flow.StateFlow 12 | import kotlinx.coroutines.launch 13 | import javax.inject.Inject 14 | 15 | @HiltViewModel 16 | class ResetPasswordViewModel @Inject constructor( 17 | private val savedStateHandle: SavedStateHandle, 18 | private val resetPassword: ResetPassword 19 | ) : BaseViewModel(), ResetPasswordView { 20 | 21 | private val _uiState = MutableStateFlow(ForgotPasswordState()) 22 | val uiState: StateFlow = _uiState 23 | 24 | override fun resetPassword(emailAddress: String) { 25 | // uiState.postValue(AuthenticationState.Loading) 26 | viewModelScope.launch { 27 | resetPassword.run( 28 | ResetPassword.Params.forResetPassword( 29 | "AIzaSyBFLpvP6vOjrl_5s_R45E6s33FOFg6y5wQ", emailAddress)) { result -> 30 | if (result.success) { 31 | // uiState.postValue(AuthenticationState.Success) 32 | } else { 33 | // uiState.postValue(AuthenticationState.Failure(result.message)) 34 | } 35 | } 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /platform_android/navigation/build.gradle: -------------------------------------------------------------------------------- 1 | import co.joebirch.minimise.buildsrc.* 2 | 3 | apply plugin: 'com.android.library' 4 | apply plugin: 'kotlin-android' 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion Versions.compileSdk 9 | 10 | defaultConfig { 11 | 12 | minSdkVersion Versions.minSdk 13 | targetSdkVersion Versions.targetSdk 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | consumerProguardFiles "consumer-rules.pro" 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | compileOptions { 27 | sourceCompatibility JavaVersion.VERSION_1_8 28 | targetCompatibility JavaVersion.VERSION_1_8 29 | } 30 | 31 | kotlinOptions { 32 | jvmTarget = "1.8" 33 | useIR = true 34 | } 35 | 36 | composeOptions { 37 | kotlinCompilerVersion Deps.Kotlin.version 38 | kotlinCompilerExtensionVersion Deps.Compose.version 39 | } 40 | } 41 | 42 | dependencies { 43 | implementation project(":platform_android:core") 44 | implementation Deps.AndroidX.appCompat 45 | implementation Deps.AndroidX.coreKtx 46 | 47 | implementation Deps.Kotlin.stdLib 48 | 49 | implementation Deps.Navigation.compose 50 | implementation Deps.Google.Hilt.hiltNavigationCompose 51 | 52 | testImplementation Deps.junit 53 | 54 | androidTestImplementation Deps.AndroidX.junit 55 | androidTestImplementation Deps.Espresso.core 56 | 57 | androidTestImplementation Deps.Mockito.core 58 | androidTestImplementation Deps.Mockito.android 59 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/ServiceKey.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | import Foundation 6 | 7 | // MARK: ServiceKeyOption 8 | 9 | public protocol ServiceKeyOption: CustomStringConvertible { 10 | func isEqualTo(_ another: ServiceKeyOption) -> Bool 11 | func hash(into: inout Hasher) 12 | } 13 | 14 | // MARK: - ServiceKey 15 | 16 | internal struct ServiceKey { 17 | internal let serviceType: Any.Type 18 | internal let argumentsType: Any.Type 19 | internal let name: String? 20 | internal let option: ServiceKeyOption? // Used for SwinjectStoryboard or other extensions. 21 | 22 | internal init( 23 | serviceType: Any.Type, 24 | argumentsType: Any.Type, 25 | name: String? = nil, 26 | option: ServiceKeyOption? = nil 27 | ) { 28 | self.serviceType = serviceType 29 | self.argumentsType = argumentsType 30 | self.name = name 31 | self.option = option 32 | } 33 | } 34 | 35 | // MARK: Hashable 36 | 37 | extension ServiceKey: Hashable { 38 | public func hash(into hasher: inout Hasher) { 39 | ObjectIdentifier(serviceType).hash(into: &hasher) 40 | ObjectIdentifier(argumentsType).hash(into: &hasher) 41 | name?.hash(into: &hasher) 42 | option?.hash(into: &hasher) 43 | } 44 | } 45 | 46 | // MARK: Equatable 47 | 48 | func == (lhs: ServiceKey, rhs: ServiceKey) -> Bool { 49 | return lhs.serviceType == rhs.serviceType 50 | && lhs.argumentsType == rhs.argumentsType 51 | && lhs.name == rhs.name 52 | && equalOptions(opt1: lhs.option, opt2: rhs.option) 53 | } 54 | 55 | private func equalOptions(opt1: ServiceKeyOption?, opt2: ServiceKeyOption?) -> Bool { 56 | switch (opt1, opt2) { 57 | case let (opt1?, opt2?): return opt1.isEqualTo(opt2) 58 | case (nil, nil): return true 59 | default: return false 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /platform_android/design/src/main/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #003b46 4 | #07575b 5 | #00262d 6 | #66a5ad 7 | #c4dfe6 8 | #75a478 9 | #3D3D3D 10 | #757575 11 | #FFFFFF 12 | #000000 13 | 14 | @color/primaryColor 15 | @color/primaryDarkColor 16 | @color/secondaryColor 17 | @color/secondaryDarkColor 18 | 19 | 20 | 21 | 22 | 23 | #e0e0e0 24 | #07575b 25 | #e53935 26 | 27 | 28 | 29 | @color/white 30 | @color/white 31 | @color/white 32 | @color/primaryDarkColor 33 | @color/text_primary 34 | @color/white 35 | 36 | 37 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/ObjectScope.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | /// A configuration how an instance provided by a `Container` is shared in the system. 6 | /// The configuration is ignored if it is applied to a value type. 7 | public protocol ObjectScopeProtocol: AnyObject { 8 | /// Used to create `InstanceStorage` to persist an instance for single service. 9 | /// Will be invoked once for each service registered in given scope. 10 | func makeStorage() -> InstanceStorage 11 | } 12 | 13 | /// Basic implementation of `ObjectScopeProtocol`. 14 | public class ObjectScope: ObjectScopeProtocol, CustomStringConvertible { 15 | public private(set) var description: String 16 | private var storageFactory: () -> InstanceStorage 17 | private let parent: ObjectScopeProtocol? 18 | 19 | /// Instantiates an `ObjectScope` with storage factory and description. 20 | /// - Parameters: 21 | /// - storageFactory: Closure for creating an `InstanceStorage` 22 | /// - description: Description of object scope for `CustomStringConvertible` implementation 23 | /// - parent: If provided, its storage will be composed with the result of `storageFactory` 24 | public init( 25 | storageFactory: @escaping () -> InstanceStorage, 26 | description: String = "", 27 | parent: ObjectScopeProtocol? = nil 28 | ) { 29 | self.storageFactory = storageFactory 30 | self.description = description 31 | self.parent = parent 32 | } 33 | 34 | /// Will invoke and return the result of `storageFactory` closure provided during initialisation. 35 | public func makeStorage() -> InstanceStorage { 36 | if let parent = parent { 37 | return CompositeStorage([storageFactory(), parent.makeStorage()]) 38 | } else { 39 | return storageFactory() 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/interactor/ResetPassword.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.interactor 2 | 3 | import co.joebirch.minimise.authentication.AuthenticationRepository 4 | import co.joebirch.minimise.shared_common.interactor.UseCase 5 | import co.joebirch.minimise.authentication.model.ResetPasswordResponse 6 | import kotlinx.coroutines.Dispatchers 7 | import kotlinx.coroutines.GlobalScope 8 | import kotlinx.coroutines.launch 9 | 10 | open class ResetPassword constructor() : UseCase() { 11 | 12 | private lateinit var authenticationRepository: AuthenticationRepository 13 | 14 | constructor(authenticationRepository: AuthenticationRepository) : this() { 15 | this.authenticationRepository = authenticationRepository 16 | } 17 | 18 | init { 19 | if (!::authenticationRepository.isInitialized) { 20 | authenticationRepository = AuthenticationRepository.create() 21 | } 22 | } 23 | 24 | override fun run(params: Params, completion: (ResetPasswordResponse) -> Unit) { 25 | GlobalScope.launch { 26 | completion(authenticationRepository.resetPassword(params.apiKey, params.emailAddress)) 27 | } 28 | } 29 | 30 | override fun runWithoutThreading(params: Params, completion: (ResetPasswordResponse) -> Unit) { 31 | GlobalScope.launch(Dispatchers.Main) { 32 | completion(authenticationRepository.resetPassword(params.apiKey, params.emailAddress)) 33 | } 34 | } 35 | 36 | open class Params private constructor( 37 | val apiKey: String, 38 | val emailAddress: String 39 | ) { 40 | companion object { 41 | 42 | fun forResetPassword( 43 | apiKey: String, 44 | emailAddress: String 45 | ) = 46 | Params( 47 | apiKey, 48 | emailAddress 49 | ) 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/interactor/AuthTest.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication.interactor 2 | 3 | import co.joebirch.minimise.authentication.interactor.Authenticate 4 | import co.joebirch.minimise.shared_authentication.MockAuthenticationDataRepository 5 | import co.joebirch.minimise.shared_authentication.runTest 6 | import co.joebirch.minimise.shared_authentication.util.AuthenticationResponseFactory.makeAuthenticationModel 7 | import co.joebirch.minimise.shared_authentication.util.DataFactory.randomString 8 | import kotlin.test.Test 9 | import kotlin.test.assertEquals 10 | 11 | class AuthTest { 12 | 13 | private val mockAuthenticationDataRepository = MockAuthenticationDataRepository() 14 | private val authenticationRepository = 15 | Authenticate( 16 | mockAuthenticationDataRepository 17 | ) 18 | 19 | @Test 20 | fun `Sign up succeeds and returns data`() = 21 | runTest { 22 | val authenticationModel = makeAuthenticationModel() 23 | mockAuthenticationDataRepository.whenSignUp = { _, _ -> authenticationModel } 24 | 25 | authenticationRepository.run( 26 | Authenticate.Params.forSignUp( 27 | randomString(), randomString(), randomString() 28 | ) 29 | ) { 30 | assertEquals(authenticationModel, it) 31 | } 32 | } 33 | 34 | @Test 35 | fun `Sign in succeeds and returns data`() = 36 | runTest { 37 | val authenticationModel = makeAuthenticationModel() 38 | mockAuthenticationDataRepository.whenSignIn = { _, _ -> authenticationModel } 39 | 40 | authenticationRepository.run( 41 | Authenticate.Params.forSignUp( 42 | randomString(), randomString(), randomString() 43 | ) 44 | ) { 45 | assertEquals(authenticationModel, it) 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Pods/Swinject/Sources/DebugHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © 2019 Swinject Contributors. All rights reserved. 3 | // 4 | 5 | internal protocol DebugHelper { 6 | func resolutionFailed( 7 | serviceType: Service.Type, 8 | key: ServiceKey, 9 | availableRegistrations: [ServiceKey: ServiceEntryProtocol] 10 | ) 11 | } 12 | 13 | internal final class LoggingDebugHelper: DebugHelper { 14 | func resolutionFailed( 15 | serviceType: Service.Type, 16 | key: ServiceKey, 17 | availableRegistrations: [ServiceKey: ServiceEntryProtocol] 18 | ) { 19 | var output = [ 20 | "Swinject: Resolution failed. Expected registration:", 21 | "\t{ \(description(serviceType: serviceType, serviceKey: key)) }", 22 | "Available registrations:", 23 | ] 24 | output += availableRegistrations 25 | .filter { $0.1 is ServiceEntry } 26 | .map { "\t{ " + $0.1.describeWithKey($0.0) + " }" } 27 | 28 | Container.log(output.joined(separator: "\n")) 29 | } 30 | } 31 | 32 | internal func description( 33 | serviceType: Any.Type, 34 | serviceKey: ServiceKey, 35 | objectScope: ObjectScopeProtocol? = nil, 36 | initCompleted: [Any] = [] 37 | ) -> String { 38 | // The protocol order in "protocol<>" is non-deterministic. 39 | let nameDescription = serviceKey.name.map { ", Name: \"\($0)\"" } ?? "" 40 | let optionDescription = serviceKey.option.map { ", \($0)" } ?? "" 41 | let initCompletedDescription = initCompleted.isEmpty ? 42 | "" : ", InitCompleted: Specified \(initCompleted.count) closures" 43 | let objectScopeDescription = objectScope.map { ", ObjectScope: \($0)" } ?? "" 44 | return "Service: \(serviceType)" 45 | + nameDescription 46 | + optionDescription 47 | + ", Factory: \(serviceKey.argumentsType) -> \(serviceKey.serviceType)" 48 | + objectScopeDescription 49 | + initCompletedDescription 50 | } 51 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonTest/kotlin/co.joebirch.minimise.shared_authentication/AuthenticationDataRepositoryTest.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.shared_authentication 2 | 3 | import co.joebirch.minimise.authentication.AuthenticationDataRepository 4 | import co.joebirch.minimise.shared_authentication.mapper.MockResetPasswordResponseMapper 5 | import co.joebirch.minimise.shared_authentication.util.AuthenticationResponseFactory.makeAuthenticationModel 6 | import co.joebirch.minimise.shared_authentication.util.AuthenticationResponseFactory.makeAuthenticationResponse 7 | import co.joebirch.minimise.shared_authentication.util.DataFactory.randomString 8 | import co.joebirch.minimise.shared_authentication.util.MockAuthenticationStore 9 | import kotlin.test.Test 10 | import kotlin.test.assertEquals 11 | 12 | class AuthenticationDataRepositoryTest { 13 | 14 | private val mockAuthenticationRemote = 15 | MockAuthenticationStore() 16 | private val mockPasswordResponseMapper = MockResetPasswordResponseMapper() 17 | private val authenticationRepository = 18 | AuthenticationDataRepository( 19 | mockAuthenticationRemote, mockPasswordResponseMapper 20 | ) 21 | 22 | @Test 23 | fun `Sign up succeeds and returns data`() = 24 | runTest { 25 | val authenticationModel = makeAuthenticationModel() 26 | 27 | mockAuthenticationRemote.whenSignUp = { _, _ -> authenticationModel } 28 | 29 | val result = authenticationRepository.signUp(randomString(), randomString(), 30 | randomString()) 31 | assertEquals(authenticationModel, result) 32 | } 33 | 34 | @Test 35 | fun `Sign in succeeds and returns data`() = 36 | runTest { 37 | val authenticationModel = makeAuthenticationModel() 38 | 39 | mockAuthenticationRemote.whenSignIn = { _, _ -> authenticationModel } 40 | 41 | val result = authenticationRepository.signIn(randomString(), randomString(), 42 | randomString()) 43 | assertEquals(authenticationModel, result) 44 | } 45 | } -------------------------------------------------------------------------------- /shared/SharedCommon/SharedCommon.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'SharedCommon' 3 | spec.version = 'unspecified' 4 | spec.homepage = '' 5 | spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" } 6 | spec.authors = '' 7 | spec.license = '' 8 | spec.summary = '' 9 | 10 | spec.static_framework = true 11 | spec.vendored_frameworks = "build/cocoapods/framework/SharedCommon.framework" 12 | spec.libraries = "c++" 13 | spec.module_name = "#{spec.name}_umbrella" 14 | 15 | 16 | 17 | 18 | 19 | spec.pod_target_xcconfig = { 20 | 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', 21 | 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', 22 | 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x64', 23 | 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', 24 | 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', 25 | 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', 26 | 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' 27 | } 28 | 29 | spec.script_phases = [ 30 | { 31 | :name => 'Build SharedCommon', 32 | :execution_position => :before_compile, 33 | :shell_path => '/bin/sh', 34 | :script => <<-SCRIPT 35 | set -ev 36 | REPO_ROOT="$PODS_TARGET_SRCROOT" 37 | "$REPO_ROOT/../../gradlew" -p "$REPO_ROOT" :shared:SharedCommon:syncFramework \ 38 | -Pkotlin.native.cocoapods.target=$KOTLIN_TARGET \ 39 | -Pkotlin.native.cocoapods.configuration=$CONFIGURATION \ 40 | -Pkotlin.native.cocoapods.cflags="$OTHER_CFLAGS" \ 41 | -Pkotlin.native.cocoapods.paths.headers="$HEADER_SEARCH_PATHS" \ 42 | -Pkotlin.native.cocoapods.paths.frameworks="$FRAMEWORK_SEARCH_PATHS" 43 | SCRIPT 44 | } 45 | ] 46 | end -------------------------------------------------------------------------------- /shared/SharedCreation/SharedCreation.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'SharedCreation' 3 | spec.version = 'unspecified' 4 | spec.homepage = '' 5 | spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" } 6 | spec.authors = '' 7 | spec.license = '' 8 | spec.summary = '' 9 | 10 | spec.static_framework = true 11 | spec.vendored_frameworks = "build/cocoapods/framework/SharedCreation.framework" 12 | spec.libraries = "c++" 13 | spec.module_name = "#{spec.name}_umbrella" 14 | 15 | 16 | 17 | 18 | 19 | spec.pod_target_xcconfig = { 20 | 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', 21 | 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', 22 | 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x64', 23 | 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', 24 | 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', 25 | 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', 26 | 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' 27 | } 28 | 29 | spec.script_phases = [ 30 | { 31 | :name => 'Build SharedCreation', 32 | :execution_position => :before_compile, 33 | :shell_path => '/bin/sh', 34 | :script => <<-SCRIPT 35 | set -ev 36 | REPO_ROOT="$PODS_TARGET_SRCROOT" 37 | "$REPO_ROOT/../../gradlew" -p "$REPO_ROOT" :shared:SharedCreation:syncFramework \ 38 | -Pkotlin.native.cocoapods.target=$KOTLIN_TARGET \ 39 | -Pkotlin.native.cocoapods.configuration=$CONFIGURATION \ 40 | -Pkotlin.native.cocoapods.cflags="$OTHER_CFLAGS" \ 41 | -Pkotlin.native.cocoapods.paths.headers="$HEADER_SEARCH_PATHS" \ 42 | -Pkotlin.native.cocoapods.paths.frameworks="$FRAMEWORK_SEARCH_PATHS" 43 | SCRIPT 44 | } 45 | ] 46 | end -------------------------------------------------------------------------------- /.github/workflows/ios_beta_release.yaml: -------------------------------------------------------------------------------- 1 | name: iOS Beta Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'iOS-[0-9]+.[0-9]+.[0-9]+' 7 | 8 | jobs: 9 | deploy: 10 | name: Deploy to Testflight 11 | runs-on: macOS-latest 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v2 15 | - uses: actions/setup-java@v1 16 | with: 17 | java-version: 11 18 | - uses: eskatos/gradle-command-action@v1 19 | with: 20 | gradle-version: 6.3-rc-1 21 | - uses: sinoru/actions-setup-xcode@v1.1 22 | with: 23 | xcode-version: '11.4' 24 | apple-id: ${{ secrets.APPLEID_USERNAME }} 25 | apple-id-password: ${{ secrets.APPLEID_PASSWORD }} 26 | - name: Update version 27 | run: | 28 | latest_beta="$(git describe --match "iOS*" --abbrev=0 --tags)" 29 | version=${latest_beta#"iOS-"} 30 | cd native/KotlinIOS 31 | xcrun agvtool new-marketing-version $version 32 | xcrun agvtool next-version -all 33 | - name: Install cocoapods 34 | run: | 35 | cd native/KotlinIOS 36 | sudo gem install cocoapods 37 | sudo bundle install 38 | - name: Install pods 39 | run: | 40 | cd native/KotlinIOS 41 | bundle exec pod install 42 | - name: Install gpg 43 | run: brew install gnupg 44 | - name: Setup provisioning profile 45 | env: 46 | IOS_KEYS: ${{ secrets.IOS_KEYS }} 47 | run: ./.github/secrets/decrypt_secrets.sh 48 | - name: Archive project 49 | env: 50 | PR_NUMBER: $(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") 51 | run: ./.github/scripts/archive_app.sh 52 | - name: Export .ipa 53 | run: ./.github/scripts/export_ipa.sh 54 | - name: Publish app to TestFlight 55 | if: success() 56 | env: 57 | APPLEID_USERNAME: ${{ secrets.APPLEID_USERNAME }} 58 | APPLEID_PASSWORD: ${{ secrets.APPLEID_PASSWORD }} 59 | run: ./.github/scripts/publish_testflight.sh 60 | -------------------------------------------------------------------------------- /shared/SharedDashboard/SharedDashboard.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'SharedDashboard' 3 | spec.version = 'unspecified' 4 | spec.homepage = '' 5 | spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" } 6 | spec.authors = '' 7 | spec.license = '' 8 | spec.summary = '' 9 | 10 | spec.static_framework = true 11 | spec.vendored_frameworks = "build/cocoapods/framework/SharedDashboard.framework" 12 | spec.libraries = "c++" 13 | spec.module_name = "#{spec.name}_umbrella" 14 | 15 | 16 | 17 | 18 | 19 | spec.pod_target_xcconfig = { 20 | 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', 21 | 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', 22 | 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x64', 23 | 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', 24 | 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', 25 | 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', 26 | 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' 27 | } 28 | 29 | spec.script_phases = [ 30 | { 31 | :name => 'Build SharedDashboard', 32 | :execution_position => :before_compile, 33 | :shell_path => '/bin/sh', 34 | :script => <<-SCRIPT 35 | set -ev 36 | REPO_ROOT="$PODS_TARGET_SRCROOT" 37 | "$REPO_ROOT/../../gradlew" -p "$REPO_ROOT" :shared:SharedDashboard:syncFramework \ 38 | -Pkotlin.native.cocoapods.target=$KOTLIN_TARGET \ 39 | -Pkotlin.native.cocoapods.configuration=$CONFIGURATION \ 40 | -Pkotlin.native.cocoapods.cflags="$OTHER_CFLAGS" \ 41 | -Pkotlin.native.cocoapods.paths.headers="$HEADER_SEARCH_PATHS" \ 42 | -Pkotlin.native.cocoapods.paths.frameworks="$FRAMEWORK_SEARCH_PATHS" 43 | SCRIPT 44 | } 45 | ] 46 | end -------------------------------------------------------------------------------- /platform_android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /native/KotlinIOS/KotlinIOS.xcodeproj/xcuserdata/joebirch.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Authentication.xcscheme_^#shared#^_ 8 | 9 | isShown 10 | 11 | orderHint 12 | 1 13 | 14 | Backend.xcscheme_^#shared#^_ 15 | 16 | orderHint 17 | 12 18 | 19 | BackendProvider.xcscheme_^#shared#^_ 20 | 21 | orderHint 22 | 34 23 | 24 | BackendService.xcscheme_^#shared#^_ 25 | 26 | orderHint 27 | 31 28 | 29 | Common.xcscheme_^#shared#^_ 30 | 31 | orderHint 32 | 13 33 | 34 | Creation.xcscheme_^#shared#^_ 35 | 36 | orderHint 37 | 12 38 | 39 | Dashboard.xcscheme_^#shared#^_ 40 | 41 | orderHint 42 | 14 43 | 44 | DashboardTests.xcscheme_^#shared#^_ 45 | 46 | orderHint 47 | 12 48 | 49 | Firebase.xcscheme_^#shared#^_ 50 | 51 | orderHint 52 | 31 53 | 54 | FirebaseTests.xcscheme_^#shared#^_ 55 | 56 | orderHint 57 | 33 58 | 59 | 60 | SuppressBuildableAutocreation 61 | 62 | 47729E0122F447C800B9B36B 63 | 64 | primary 65 | 66 | 67 | 47729E1522F447CA00B9B36B 68 | 69 | primary 70 | 71 | 72 | 47729E2022F447CA00B9B36B 73 | 74 | primary 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /shared/SharedAuthentication/src/commonMain/kotlin/co.joebirch.minimise.authentication/remote/AuthenticationRemoteStore.kt: -------------------------------------------------------------------------------- 1 | package co.joebirch.minimise.authentication.remote 2 | 3 | import co.joebirch.minimise.BuildKonfig 4 | import co.joebirch.minimise.SignInQuery 5 | import co.joebirch.minimise.SignUpMutation 6 | import co.joebirch.minimise.authentication.mapper.toAuthenticationModel 7 | import co.joebirch.minimise.authentication.model.AuthenticationModel 8 | import com.apollographql.apollo.ApolloClient 9 | import com.apollographql.apollo.api.ApolloExperimental 10 | import com.apollographql.apollo.network.http.ApolloHttpNetworkTransport 11 | import kotlinx.coroutines.ExperimentalCoroutinesApi 12 | import kotlinx.coroutines.flow.single 13 | 14 | @ExperimentalCoroutinesApi 15 | @ApolloExperimental 16 | open class AuthenticationRemoteStore : AuthenticationRemote { 17 | 18 | private val apolloClient = ApolloClient( 19 | networkTransport = ApolloHttpNetworkTransport( 20 | serverUrl = BuildKonfig.apiUrl, 21 | headers = mapOf( 22 | "Accept" to "application/json", 23 | "Content-Type" to "application/json" 24 | ) 25 | ) 26 | ) 27 | 28 | override suspend fun signUp( 29 | apiKey: String, 30 | emailAddress: String, 31 | password: String 32 | ): AuthenticationModel { 33 | val signUp = SignUpMutation( 34 | emailAddress = emailAddress, 35 | password = password 36 | ) 37 | val s = apolloClient.mutate(signUp).execute().single() 38 | return s.data?.createUser?.toAuthenticationModel() 39 | ?: AuthenticationModel() 40 | } 41 | 42 | override suspend fun signIn( 43 | apiKey: String, 44 | emailAddress: String, 45 | password: String 46 | ): AuthenticationModel { 47 | val repositoriesQuery = SignInQuery( 48 | emailAddress = emailAddress, 49 | password = password 50 | ) 51 | return apolloClient.query(repositoriesQuery).execute().single().data?.login 52 | ?.toAuthenticationModel() ?: AuthenticationModel() 53 | } 54 | } -------------------------------------------------------------------------------- /shared/SharedAuthentication/SharedAuthentication.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'SharedAuthentication' 3 | spec.version = '1.0' 4 | spec.homepage = 'www.joebirch.co' 5 | spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" } 6 | spec.authors = '' 7 | spec.license = '' 8 | spec.summary = 'Shared Authentication' 9 | 10 | spec.static_framework = true 11 | spec.vendored_frameworks = "build/cocoapods/framework/SharedAuthentication.framework" 12 | spec.libraries = "c++" 13 | spec.module_name = "#{spec.name}_umbrella" 14 | 15 | 16 | 17 | 18 | 19 | spec.pod_target_xcconfig = { 20 | 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', 21 | 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', 22 | 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x64', 23 | 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', 24 | 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', 25 | 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', 26 | 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' 27 | } 28 | 29 | spec.script_phases = [ 30 | { 31 | :name => 'Build SharedAuthentication', 32 | :execution_position => :before_compile, 33 | :shell_path => '/bin/sh', 34 | :script => <<-SCRIPT 35 | set -ev 36 | REPO_ROOT="$PODS_TARGET_SRCROOT" 37 | "$REPO_ROOT/../../gradlew" -p "$REPO_ROOT" :shared:SharedAuthentication:syncFramework \ 38 | -Pkotlin.native.cocoapods.target=$KOTLIN_TARGET \ 39 | -Pkotlin.native.cocoapods.configuration=$CONFIGURATION \ 40 | -Pkotlin.native.cocoapods.cflags="$OTHER_CFLAGS" \ 41 | -Pkotlin.native.cocoapods.paths.headers="$HEADER_SEARCH_PATHS" \ 42 | -Pkotlin.native.cocoapods.paths.frameworks="$FRAMEWORK_SEARCH_PATHS" 43 | SCRIPT 44 | } 45 | ] 46 | end --------------------------------------------------------------------------------