├── .fleet └── settings.json ├── .github ├── ci-gradle.properties └── workflows │ └── Check.yaml ├── .gitignore ├── LICENSE.txt ├── README.MD ├── assets ├── icon.png ├── screenshots │ ├── android │ │ ├── Screenshot_1.png │ │ ├── Screenshot_2.png │ │ ├── Screenshot_3.png │ │ ├── Screenshot_4.png │ │ ├── Screenshot_5.png │ │ ├── Screenshot_6.png │ │ ├── Screenshot_7.png │ │ └── Screenshot_8.png │ └── ios │ │ ├── Screenshot_1.png │ │ ├── Screenshot_2.png │ │ ├── Screenshot_3.png │ │ ├── Screenshot_4.png │ │ ├── Screenshot_5.png │ │ └── Screenshot_6.png └── splashy_banner.png ├── build.gradle.kts ├── cleanup.sh ├── composeApp ├── build.gradle.kts ├── proguard-rules.pro └── src │ ├── androidDebug │ └── res │ │ └── values │ │ └── strings.xml │ ├── androidMain │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── kotlin │ │ └── dev │ │ │ └── ishubhamsingh │ │ │ └── splashy │ │ │ ├── App.android.kt │ │ │ ├── MainActivity.kt │ │ │ ├── SplashyApp.kt │ │ │ └── core │ │ │ ├── di │ │ │ └── components │ │ │ │ └── PlatformModule.kt │ │ │ ├── presentation │ │ │ └── SplashyTheme.kt │ │ │ └── utils │ │ │ ├── CommonUtils.kt │ │ │ ├── DatabaseDriverFactory.kt │ │ │ └── FileUtils.kt │ └── res │ │ ├── mipmap-anydpi-v26 │ │ └── ic_launcher.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_monochrome.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_monochrome.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_monochrome.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_monochrome.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_background.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_monochrome.png │ │ ├── values-v29 │ │ └── style.xml │ │ └── values │ │ ├── strings.xml │ │ └── style.xml │ ├── commonMain │ ├── composeResources │ │ ├── drawable │ │ │ └── hat.png │ │ ├── font │ │ │ ├── lato_black.ttf │ │ │ ├── lato_bold.ttf │ │ │ ├── lato_light.ttf │ │ │ ├── lato_regular.ttf │ │ │ ├── lato_thin.ttf │ │ │ └── lobster_regular.ttf │ │ └── values │ │ │ └── strings.xml │ ├── kotlin │ │ └── dev │ │ │ └── ishubhamsingh │ │ │ └── splashy │ │ │ ├── App.kt │ │ │ ├── core │ │ │ ├── di │ │ │ │ ├── ApplicationModule.kt │ │ │ │ └── components │ │ │ │ │ ├── CommonModule.kt │ │ │ │ │ └── PlatformModule.kt │ │ │ ├── domain │ │ │ │ ├── NetworkResult.kt │ │ │ │ ├── ScreenEvent.kt │ │ │ │ └── UnsplashRepository.kt │ │ │ ├── navigation │ │ │ │ ├── SplashyAppState.kt │ │ │ │ └── TopLevelScreen.kt │ │ │ ├── network │ │ │ │ ├── KtorLogger.kt │ │ │ │ ├── UnsplashRepositoryImpl.kt │ │ │ │ └── api │ │ │ │ │ └── UnsplashApi.kt │ │ │ ├── presentation │ │ │ │ └── SplashyTheme.kt │ │ │ └── utils │ │ │ │ ├── CommonUtils.kt │ │ │ │ ├── DIHelper.kt │ │ │ │ ├── DatabaseDriverFactory.kt │ │ │ │ ├── Extensions.kt │ │ │ │ ├── FileUtils.kt │ │ │ │ ├── Logging.kt │ │ │ │ └── SettingsUtils.kt │ │ │ ├── db │ │ │ ├── Database.kt │ │ │ ├── columnAdapters │ │ │ │ ├── IntAdapter.kt │ │ │ │ ├── LinksAdapter.kt │ │ │ │ ├── TopicSubmissionsAdapter.kt │ │ │ │ ├── UrlsAdapter.kt │ │ │ │ └── UserAdapter.kt │ │ │ └── mappers │ │ │ │ ├── FavouriteMapper.kt │ │ │ │ └── PhotoMapper.kt │ │ │ ├── features │ │ │ ├── about │ │ │ │ └── ui │ │ │ │ │ └── AboutComponent.kt │ │ │ ├── categories │ │ │ │ ├── CategoriesScreenModel.kt │ │ │ │ └── ui │ │ │ │ │ ├── CategoriesEvent.kt │ │ │ │ │ ├── CategoriesState.kt │ │ │ │ │ └── CategoriesTab.kt │ │ │ ├── categoriesPhotos │ │ │ │ ├── CategoriesPhotosScreenModel.kt │ │ │ │ └── ui │ │ │ │ │ ├── CategoriesPhotosEvent.kt │ │ │ │ │ ├── CategoriesPhotosScreen.kt │ │ │ │ │ └── CategoriesPhotosState.kt │ │ │ ├── details │ │ │ │ ├── DetailsScreenModel.kt │ │ │ │ └── ui │ │ │ │ │ ├── DetailsEvent.kt │ │ │ │ │ ├── DetailsScreen.kt │ │ │ │ │ └── DetailsState.kt │ │ │ ├── favourites │ │ │ │ ├── FavouritesScreenModel.kt │ │ │ │ └── ui │ │ │ │ │ ├── FavouritesEvent.kt │ │ │ │ │ ├── FavouritesState.kt │ │ │ │ │ └── FavouritesTab.kt │ │ │ ├── home │ │ │ │ ├── HomeScreenModel.kt │ │ │ │ └── ui │ │ │ │ │ ├── HomeEvent.kt │ │ │ │ │ ├── HomeState.kt │ │ │ │ │ └── HomeTab.kt │ │ │ └── settings │ │ │ │ ├── SettingsScreenModel.kt │ │ │ │ └── ui │ │ │ │ ├── SettingsEvent.kt │ │ │ │ ├── SettingsScreen.kt │ │ │ │ └── SettingsState.kt │ │ │ ├── models │ │ │ ├── CollectionItem.kt │ │ │ ├── DownloadUrl.kt │ │ │ ├── Favourite.kt │ │ │ ├── Links.kt │ │ │ ├── LinksX.kt │ │ │ ├── Photo.kt │ │ │ ├── PhotoSearchCollection.kt │ │ │ ├── ProfileImage.kt │ │ │ ├── Social.kt │ │ │ ├── Sponsor.kt │ │ │ ├── Sponsorship.kt │ │ │ ├── Topic.kt │ │ │ ├── TopicFilter.kt │ │ │ ├── TopicSubmissionStatus.kt │ │ │ ├── TopicSubmissions.kt │ │ │ ├── Urls.kt │ │ │ └── User.kt │ │ │ └── ui │ │ │ ├── components │ │ │ └── ComposeReusables.kt │ │ │ └── theme │ │ │ ├── Color.kt │ │ │ ├── Theme.kt │ │ │ └── Typography.kt │ └── sqldelight │ │ └── dev │ │ └── ishubhamsingh │ │ └── splashy │ │ └── db │ │ ├── Favourite.sq │ │ └── Photo.sq │ └── iosMain │ └── kotlin │ └── dev │ └── ishubhamsingh │ └── splashy │ ├── App.ios.kt │ └── core │ ├── di.components │ └── PlatformModule.kt │ ├── presentation │ └── SplashyTheme.kt │ └── utils │ ├── CommonUtils.kt │ ├── DatabaseDriverFactory.kt │ └── FileUtils.kt ├── gradle.bat ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── iosApp ├── Configuration │ └── Config.xcconfig ├── iosApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── iosApp.xcscheme └── iosApp │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── AppIcon-20@2x.png │ │ ├── AppIcon-20@2x~ipad.png │ │ ├── AppIcon-20@3x.png │ │ ├── AppIcon-20~ipad.png │ │ ├── AppIcon-29.png │ │ ├── AppIcon-29@2x.png │ │ ├── AppIcon-29@2x~ipad.png │ │ ├── AppIcon-29@3x.png │ │ ├── AppIcon-29~ipad.png │ │ ├── AppIcon-40@2x.png │ │ ├── AppIcon-40@2x~ipad.png │ │ ├── AppIcon-40@3x.png │ │ ├── AppIcon-40~ipad.png │ │ ├── AppIcon-60@2x~car.png │ │ ├── AppIcon-60@3x~car.png │ │ ├── AppIcon-83.5@2x~ipad.png │ │ ├── AppIcon@2x.png │ │ ├── AppIcon@2x~ipad.png │ │ ├── AppIcon@3x.png │ │ ├── AppIcon~ios-marketing.png │ │ ├── AppIcon~ipad.png │ │ └── Contents.json │ └── Contents.json │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ ├── info.plist │ └── iosApp.swift ├── keystore └── splashy.jks ├── renovate.json ├── settings.gradle.kts └── spotless └── copyright.txt /.fleet/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true 3 | } -------------------------------------------------------------------------------- /.github/ci-gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.daemon=false 2 | org.gradle.parallel=true 3 | org.gradle.jvmargs=-Xmx5120m 4 | org.gradle.workers.max=2 5 | 6 | kotlin.incremental=false 7 | kotlin.compiler.execution.strategy=in-process -------------------------------------------------------------------------------- /.github/workflows/Check.yaml: -------------------------------------------------------------------------------- 1 | name: Check 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | concurrency: 12 | group: ci-${{ github.ref }} 13 | cancel-in-progress: true 14 | 15 | jobs: 16 | build: 17 | runs-on: macos-latest 18 | timeout-minutes: 30 19 | 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v4 23 | 24 | - name: Copy CI gradle.properties 25 | run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties 26 | 27 | - name: Retrieve the secret and decode it to a file 28 | env: 29 | SECRETS_BASE64: ${{ secrets.SECRETS_BASE64 }} 30 | run: | 31 | echo $SECRETS_BASE64 | base64 --decode > secrets.properties 32 | 33 | - name: Set up JDK 17 34 | uses: actions/setup-java@v4 35 | with: 36 | java-version: 17 37 | distribution: zulu 38 | cache: 'gradle' 39 | 40 | - name: Check formatting and build apk 41 | run: ./gradlew spotlessCheck lintRelease :composeApp:assembleRelease --stacktrace 42 | 43 | - name: Upload build outputs (APKs) 44 | uses: actions/upload-artifact@v4 45 | with: 46 | name: build-outputs 47 | path: composeApp/build/outputs/apk 48 | 49 | - name: Upload build reports 50 | if: always() 51 | uses: actions/upload-artifact@v4 52 | with: 53 | name: build-reports 54 | path: composeApp/build/reports -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.iml 3 | .gradle 4 | .idea 5 | .DS_Store 6 | build 7 | */build 8 | captures 9 | .externalNativeBuild 10 | .cxx 11 | .kotlin 12 | local.properties 13 | xcuserdata/ 14 | *yarn.lock 15 | secrets.properties 16 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |
6 | 7 |

8 | 9 |
10 | Splashy 11 |

12 | 13 | An Unsplash based wallpaper app built with Compose Multiplatform and KMP for Android and iOS. 14 | 15 | [![Check](https://github.com/ishubhamsingh/Splashy/actions/workflows/Check.yaml/badge.svg?branch=main)](https://github.com/ishubhamsingh/Splashy/actions/workflows/Check.yaml) 16 | 17 | 18 | ## :hammer_and_wrench: Tech Stack 19 | 20 | - [Kotlin Mutliplatform](https://kotlinlang.org/lp/multiplatform/) 21 | - [Compose Multiplatform](https://www.jetbrains.com/lp/compose-multiplatform/) 22 | - [Ktor Client](https://ktor.io/) 23 | - [SQLDelight](https://cashapp.github.io/sqldelight/2.0.0/) 24 | - [Voyager](https://github.com/adrielcafe/voyager) 25 | - [Koin](https://insert-koin.io/) 26 | - [Kamel](https://github.com/Kamel-Media/Kamel) 27 | - [Napier](https://github.com/AAkira/Napier) 28 | - [Compose Icons](https://github.com/DevSrSouza/compose-icons) 29 | - [Moko Permissions](https://github.com/icerockdev/moko-permissions) 30 | 31 | ## :camera_flash: Screenshots 32 | 33 | ### Android 34 | 35 | 36 | 37 | ### iOS 38 | 39 | 40 | 41 | ## :gear: Build 42 | 43 | The app uses Unsplash API, hence you need to get your own API key from [here](https://unsplash.com/documentation). 44 | In order to sign your builds generate `splashy.jks` keystore and add keystore password, alias and store password in `secrets.properties`. 45 | 46 | secrets.properties would look like this: 47 | ``` 48 | unsplash.access.key=#Add your unsplash key 49 | splashy.keystore.password=#Add your keystore password 50 | splashy.key.alias=#Add your key alias 51 | splashy.key.password=#Add your key password 52 | ``` 53 | 54 | ## License 55 | ``` 56 | Copyright Shubham Singh 57 | 58 | Licensed under the Apache License, Version 2.0 (the "License"); 59 | you may not use this file except in compliance with the License. 60 | You may obtain a copy of the License at 61 | 62 | https://www.apache.org/licenses/LICENSE-2.0 63 | 64 | Unless required by applicable law or agreed to in writing, software 65 | distributed under the License is distributed on an "AS IS" BASIS, 66 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 67 | See the License for the specific language governing permissions and 68 | limitations under the License. 69 | ``` -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/icon.png -------------------------------------------------------------------------------- /assets/screenshots/android/Screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/android/Screenshot_1.png -------------------------------------------------------------------------------- /assets/screenshots/android/Screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/android/Screenshot_2.png -------------------------------------------------------------------------------- /assets/screenshots/android/Screenshot_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/android/Screenshot_3.png -------------------------------------------------------------------------------- /assets/screenshots/android/Screenshot_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/android/Screenshot_4.png -------------------------------------------------------------------------------- /assets/screenshots/android/Screenshot_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/android/Screenshot_5.png -------------------------------------------------------------------------------- /assets/screenshots/android/Screenshot_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/android/Screenshot_6.png -------------------------------------------------------------------------------- /assets/screenshots/android/Screenshot_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/android/Screenshot_7.png -------------------------------------------------------------------------------- /assets/screenshots/android/Screenshot_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/android/Screenshot_8.png -------------------------------------------------------------------------------- /assets/screenshots/ios/Screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/ios/Screenshot_1.png -------------------------------------------------------------------------------- /assets/screenshots/ios/Screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/ios/Screenshot_2.png -------------------------------------------------------------------------------- /assets/screenshots/ios/Screenshot_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/ios/Screenshot_3.png -------------------------------------------------------------------------------- /assets/screenshots/ios/Screenshot_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/ios/Screenshot_4.png -------------------------------------------------------------------------------- /assets/screenshots/ios/Screenshot_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/ios/Screenshot_5.png -------------------------------------------------------------------------------- /assets/screenshots/ios/Screenshot_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/screenshots/ios/Screenshot_6.png -------------------------------------------------------------------------------- /assets/splashy_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/assets/splashy_banner.png -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | import com.diffplug.gradle.spotless.SpotlessExtension 17 | 18 | plugins { 19 | alias(libs.plugins.multiplatform).apply(false) 20 | alias(libs.plugins.compose).apply(false) 21 | alias(libs.plugins.compose.compiler).apply(false) 22 | alias(libs.plugins.cocoapods).apply(false) 23 | alias(libs.plugins.android.application).apply(false) 24 | alias(libs.plugins.buildConfig).apply(false) 25 | alias(libs.plugins.kotlinx.serialization).apply(false) 26 | alias(libs.plugins.sqlDelight).apply(false) 27 | alias(libs.plugins.spotless).apply(false) 28 | } 29 | 30 | allprojects { 31 | apply(plugin = rootProject.libs.plugins.spotless.get().pluginId) 32 | configure { 33 | kotlin { 34 | ktfmt(libs.versions.ktfmt.get()).googleStyle() 35 | target("**/*.kt") 36 | targetExclude("$projectDir/build/**/*.kt") 37 | licenseHeaderFile(rootProject.file("spotless/copyright.txt")) 38 | } 39 | kotlinGradle { 40 | ktfmt(libs.versions.ktfmt.get()).googleStyle() 41 | target("**/*.kts") 42 | targetExclude("$projectDir/build/**/*.kts") 43 | licenseHeaderFile(rootProject.file("spotless/copyright.txt"), "(^(?![\\/ ]\\*).*$)") 44 | } 45 | format("xml") { 46 | target("**/*.xml") 47 | targetExclude("**/build/", ".idea/") 48 | trimTrailingWhitespace() 49 | endWithNewline() 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -rf .idea 3 | ./gradlew clean 4 | rm -rf .gradle 5 | rm -rf build 6 | rm -rf */build 7 | rm -rf iosApp/iosApp.xcworkspace 8 | rm -rf iosApp/Pods 9 | rm -rf iosApp/iosApp.xcodeproj/project.xcworkspace 10 | rm -rf iosApp/iosApp.xcodeproj/xcuserdata 11 | -------------------------------------------------------------------------------- /composeApp/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -dontwarn org.slf4j.impl.StaticLoggerBinder 2 | -dontwarn kotlinx.serialization.KSerializer 3 | -dontwarn kotlinx.serialization.Serializable 4 | -keep class io.kamel.** { *; } 5 | -keep class dev.ishubhamsingh.splashy.models.** { *; } -------------------------------------------------------------------------------- /composeApp/src/androidDebug/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Splashy Debug 3 | 4 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/ic_launcher-playstore.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/kotlin/dev/ishubhamsingh/splashy/App.android.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy 17 | 18 | import androidx.compose.foundation.isSystemInDarkTheme 19 | import androidx.compose.runtime.Composable 20 | 21 | @Composable fun AppView() = App(darkTheme = isSystemInDarkTheme(), dynamicColor = true) 22 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/kotlin/dev/ishubhamsingh/splashy/MainActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy 17 | 18 | import android.os.Bundle 19 | import androidx.activity.compose.setContent 20 | import androidx.appcompat.app.AppCompatActivity 21 | import androidx.core.view.WindowCompat 22 | 23 | class MainActivity : AppCompatActivity() { 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | WindowCompat.setDecorFitsSystemWindows(window, false) 27 | setContent { AppView() } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/kotlin/dev/ishubhamsingh/splashy/SplashyApp.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy 17 | 18 | import android.app.Application 19 | import dev.ishubhamsingh.splashy.core.di.appModule 20 | import dev.ishubhamsingh.splashy.core.utils.initialiseLogging 21 | import org.koin.android.ext.koin.androidContext 22 | import org.koin.android.ext.koin.androidLogger 23 | import org.koin.core.context.startKoin 24 | 25 | class SplashyApp : Application() { 26 | companion object { 27 | lateinit var INSTANCE: SplashyApp 28 | } 29 | 30 | override fun onCreate() { 31 | super.onCreate() 32 | INSTANCE = this 33 | startKoin { 34 | androidContext(INSTANCE) 35 | androidLogger() 36 | modules(appModule()) 37 | } 38 | initialiseLogging() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/kotlin/dev/ishubhamsingh/splashy/core/di/components/PlatformModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.di.components 17 | 18 | import dev.ishubhamsingh.splashy.core.utils.DatabaseDriverFactory 19 | import dev.ishubhamsingh.splashy.core.utils.FileUtils 20 | import org.koin.dsl.module 21 | 22 | /** Created by Shubham Singh on 11/08/23. */ 23 | actual val platformModule = module { 24 | single { DatabaseDriverFactory(get()) } 25 | factory { FileUtils(get()) } 26 | } 27 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/kotlin/dev/ishubhamsingh/splashy/core/presentation/SplashyTheme.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.presentation 17 | 18 | import android.os.Build 19 | import androidx.compose.material3.MaterialTheme 20 | import androidx.compose.material3.dynamicDarkColorScheme 21 | import androidx.compose.material3.dynamicLightColorScheme 22 | import androidx.compose.runtime.Composable 23 | import androidx.compose.ui.platform.LocalContext 24 | import dev.ishubhamsingh.splashy.ui.theme.DarkColors 25 | import dev.ishubhamsingh.splashy.ui.theme.LightColors 26 | import dev.ishubhamsingh.splashy.ui.theme.Shapes 27 | import dev.ishubhamsingh.splashy.ui.theme.getTypography 28 | 29 | @Composable 30 | actual fun SplashyTheme( 31 | darkTheme: Boolean, 32 | dynamicColor: Boolean, 33 | content: @Composable () -> Unit 34 | ) { 35 | val colorScheme = 36 | when { 37 | dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { 38 | val context = LocalContext.current 39 | if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) 40 | } 41 | darkTheme -> DarkColors 42 | else -> LightColors 43 | } 44 | 45 | MaterialTheme( 46 | colorScheme = colorScheme, 47 | typography = getTypography(), 48 | shapes = Shapes, 49 | content = content 50 | ) 51 | } 52 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/kotlin/dev/ishubhamsingh/splashy/core/utils/CommonUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import android.app.Activity 19 | import androidx.compose.runtime.Composable 20 | import androidx.compose.ui.graphics.Color 21 | import androidx.compose.ui.graphics.toArgb 22 | import androidx.compose.ui.platform.LocalContext 23 | import androidx.compose.ui.platform.LocalView 24 | import androidx.core.view.WindowCompat 25 | import dev.ishubhamsingh.splashy.BuildConfig 26 | import io.ktor.client.HttpClient 27 | import io.ktor.client.engine.okhttp.OkHttp 28 | import java.time.Duration 29 | import java.time.ZonedDateTime 30 | import java.time.format.DateTimeFormatter 31 | 32 | actual fun getHttpClient(): HttpClient { 33 | val httpClient = 34 | HttpClient(OkHttp) { 35 | engine { 36 | config { 37 | retryOnConnectionFailure(true) 38 | callTimeout(Duration.ofMinutes(0)) 39 | connectTimeout(Duration.ofMinutes(0)) 40 | readTimeout(Duration.ofMinutes(0)) 41 | writeTimeout(Duration.ofMinutes(0)) 42 | } 43 | } 44 | } 45 | 46 | return httpClient 47 | } 48 | 49 | actual fun getFormattedDateTime(timestamp: String, format: String): String { 50 | val date = ZonedDateTime.parse(timestamp) 51 | val formatter = DateTimeFormatter.ofPattern(format) 52 | return date.format(formatter) 53 | } 54 | 55 | actual fun getPlatform(): Platform = Platform.Android 56 | 57 | actual fun isDebug(): Boolean = BuildConfig.DEBUG 58 | 59 | @Composable 60 | actual fun getScreenHeight(): Int { 61 | return LocalContext.current.resources.displayMetrics.heightPixels 62 | } 63 | 64 | @Composable 65 | actual fun UpdateSystemBars( 66 | statusBarColor: Color, 67 | navigationBarColor: Color, 68 | isDarkTheme: Boolean 69 | ) { 70 | val view = LocalView.current 71 | val window = (view.context as? Activity)?.window ?: return 72 | window.statusBarColor = statusBarColor.toArgb() 73 | window.navigationBarColor = navigationBarColor.toArgb() 74 | WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !isDarkTheme 75 | } 76 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/kotlin/dev/ishubhamsingh/splashy/core/utils/DatabaseDriverFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import android.content.Context 19 | import app.cash.sqldelight.db.SqlDriver 20 | import app.cash.sqldelight.driver.android.AndroidSqliteDriver 21 | import dev.ishubhamsingh.splashy.db.SplashyDatabase 22 | 23 | /** Created by Shubham Singh on 11/08/23. */ 24 | actual class DatabaseDriverFactory(private val context: Context) { 25 | actual fun createDriver(): SqlDriver { 26 | return AndroidSqliteDriver(schema = SplashyDatabase.Schema, context = context, name = DB_NAME) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/kotlin/dev/ishubhamsingh/splashy/core/utils/FileUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import android.app.WallpaperManager 19 | import android.app.WallpaperManager.FLAG_LOCK 20 | import android.app.WallpaperManager.FLAG_SYSTEM 21 | import android.content.ContentValues 22 | import android.content.Context 23 | import android.content.Intent 24 | import android.content.Intent.FLAG_ACTIVITY_NEW_TASK 25 | import android.graphics.Bitmap 26 | import android.graphics.BitmapFactory 27 | import android.net.Uri 28 | import android.os.Build 29 | import android.os.Environment 30 | import android.provider.MediaStore 31 | import android.widget.Toast 32 | import com.eygraber.uri.toAndroidUri 33 | import com.eygraber.uri.toUri 34 | import dev.ishubhamsingh.splashy.features.details.WallpaperScreenType 35 | import dev.ishubhamsingh.splashy.resources.Res 36 | import dev.ishubhamsingh.splashy.resources.applying_wallpaper_failed_message 37 | import dev.ishubhamsingh.splashy.resources.applying_wallpaper_success_message 38 | import dev.ishubhamsingh.splashy.resources.downloading_file_failed_message 39 | import dev.ishubhamsingh.splashy.resources.downloading_file_success_message 40 | import dev.ishubhamsingh.splashy.resources.opening_file_failed_message 41 | import dev.ishubhamsingh.splashy.resources.wallpaper_chooser_title 42 | import kotlin.coroutines.coroutineContext 43 | import kotlinx.coroutines.CoroutineScope 44 | import kotlinx.coroutines.Dispatchers 45 | import kotlinx.coroutines.launch 46 | import org.jetbrains.compose.resources.getString 47 | 48 | /** Created by Shubham Singh on 19/08/23. */ 49 | actual class FileUtils(private val context: Context) { 50 | 51 | actual suspend fun saveByteArrayToFile( 52 | fileName: String, 53 | data: ByteArray, 54 | shouldOpenFile: Boolean, 55 | updateMessage: (String) -> Unit 56 | ) { 57 | var uri: Uri? = null 58 | var result = "" 59 | 60 | CoroutineScope(coroutineContext).launch(Dispatchers.IO) { 61 | runCatching { 62 | val imageBitmap = BitmapFactory.decodeByteArray(data, 0, data.size) 63 | 64 | val mContentValues = 65 | ContentValues().apply { 66 | put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis()) 67 | put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") 68 | put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES) 69 | put(MediaStore.Images.Media.DISPLAY_NAME, fileName) 70 | } 71 | 72 | context.contentResolver 73 | .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mContentValues) 74 | .apply { 75 | uri = this 76 | uri?.let { 77 | context.contentResolver.openOutputStream(it)?.let { outStream -> 78 | imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream) 79 | } 80 | } 81 | } 82 | } 83 | .onSuccess { 84 | if (shouldOpenFile) { 85 | openFile(uri?.toUri(), fileName) 86 | } else { 87 | result = 88 | getString(Res.string.downloading_file_success_message, Environment.DIRECTORY_PICTURES) 89 | updateMessage.invoke(result) 90 | } 91 | } 92 | .onFailure { 93 | result = 94 | if (shouldOpenFile) { 95 | getString(Res.string.opening_file_failed_message) 96 | } else { 97 | getString(Res.string.downloading_file_failed_message) 98 | } 99 | updateMessage.invoke(result) 100 | it.printStackTrace() 101 | } 102 | } 103 | } 104 | 105 | actual suspend fun openFile(uri: com.eygraber.uri.Uri?, fileName: String) { 106 | val intent = Intent(Intent.ACTION_ATTACH_DATA) 107 | intent.addFlags(FLAG_ACTIVITY_NEW_TASK) 108 | intent.addCategory(Intent.CATEGORY_DEFAULT) 109 | intent.setDataAndType(uri?.toAndroidUri(), "image/jpeg") 110 | intent.putExtra("mimeType", "image/jpeg") 111 | val chooserIntent = 112 | Intent.createChooser(intent, getString(Res.string.wallpaper_chooser_title, fileName)) 113 | chooserIntent.addFlags(FLAG_ACTIVITY_NEW_TASK) 114 | context.startActivity(chooserIntent) 115 | } 116 | 117 | actual suspend fun applyWallpaper( 118 | data: ByteArray, 119 | wallpaperScreenType: WallpaperScreenType, 120 | updateMessage: (String) -> Unit 121 | ) { 122 | val wallpaperManager = WallpaperManager.getInstance(context) 123 | var result = "" 124 | val flag = 125 | when (wallpaperScreenType) { 126 | WallpaperScreenType.HOME_SCREEN -> FLAG_SYSTEM 127 | WallpaperScreenType.LOCK_SCREEN -> FLAG_LOCK 128 | WallpaperScreenType.BOTH -> FLAG_SYSTEM or FLAG_LOCK 129 | else -> FLAG_SYSTEM 130 | } 131 | 132 | CoroutineScope(coroutineContext).launch(Dispatchers.Default) { 133 | runCatching { 134 | val imageBitmap = BitmapFactory.decodeByteArray(data, 0, data.size) 135 | wallpaperManager.setBitmap(imageBitmap, null, true, flag) 136 | } 137 | .onSuccess { 138 | result = getString(Res.string.applying_wallpaper_success_message) 139 | updateMessage.invoke(result) 140 | } 141 | .onFailure { 142 | result = getString(Res.string.applying_wallpaper_failed_message) 143 | showMessage(result) 144 | updateMessage.invoke(result) 145 | } 146 | } 147 | } 148 | 149 | actual suspend fun shouldAskStorageRuntimePermission(): Boolean { 150 | return Build.VERSION.SDK_INT < Build.VERSION_CODES.Q 151 | } 152 | 153 | actual suspend fun showMessage(message: String) { 154 | CoroutineScope(coroutineContext).launch(Dispatchers.Main) { 155 | Toast.makeText(context, message, Toast.LENGTH_SHORT).show() 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-hdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-mdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xxhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_monochrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_monochrome.png -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/values-v29/style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Splashy 3 | 4 | -------------------------------------------------------------------------------- /composeApp/src/androidMain/res/values/style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/composeResources/drawable/hat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/commonMain/composeResources/drawable/hat.png -------------------------------------------------------------------------------- /composeApp/src/commonMain/composeResources/font/lato_black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/commonMain/composeResources/font/lato_black.ttf -------------------------------------------------------------------------------- /composeApp/src/commonMain/composeResources/font/lato_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/commonMain/composeResources/font/lato_bold.ttf -------------------------------------------------------------------------------- /composeApp/src/commonMain/composeResources/font/lato_light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/commonMain/composeResources/font/lato_light.ttf -------------------------------------------------------------------------------- /composeApp/src/commonMain/composeResources/font/lato_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/commonMain/composeResources/font/lato_regular.ttf -------------------------------------------------------------------------------- /composeApp/src/commonMain/composeResources/font/lato_thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/commonMain/composeResources/font/lato_thin.ttf -------------------------------------------------------------------------------- /composeApp/src/commonMain/composeResources/font/lobster_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/composeApp/src/commonMain/composeResources/font/lobster_regular.ttf -------------------------------------------------------------------------------- /composeApp/src/commonMain/composeResources/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Splashy 3 | Filter by Categories 4 | Save to Gallery 5 | Download 6 | Set Wallpaper 7 | DETAILS 8 | Description: 9 | Posted on: 10 | Size: 11 | Likes: 12 | Color: 13 | Categories: 14 | Search 15 | 16 | Set Wallpaper 17 | Please select how you want to set the wallpaper 18 | Set using other app 19 | Set on Homescreen 20 | Set on Lockscreen 21 | Set on both screens 22 | 23 | Home 24 | Categories 25 | Favorites 26 | Photo Details 27 | Category Photos 28 | Settings 29 | 30 | Saved to gallery successfully 31 | Saving to gallery failed! 32 | Opening file failed! 33 | File saved successfully in %1$s 34 | Saving file failed! 35 | Wallpaper set successfully 36 | Setting wallpaper failed! 37 | Set %1$s as: 38 | 39 | Collections 40 | Categories 41 | %1$d Photos 42 | 43 | Select Theme 44 | Use Material You 45 | Apply wallpaper based colors 46 | 47 | System 48 | Light 49 | Dark 50 | 51 | back 52 | 53 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/App.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy 17 | 18 | import androidx.compose.runtime.Composable 19 | import androidx.compose.runtime.LaunchedEffect 20 | import androidx.compose.runtime.mutableStateOf 21 | import cafe.adriel.voyager.navigator.Navigator 22 | import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior 23 | import cafe.adriel.voyager.transitions.SlideTransition 24 | import dev.ishubhamsingh.splashy.core.navigation.TopLevelScreen 25 | import dev.ishubhamsingh.splashy.core.presentation.SplashyTheme 26 | import dev.ishubhamsingh.splashy.core.utils.SettingsUtils 27 | import dev.ishubhamsingh.splashy.features.settings.Theme 28 | import org.koin.compose.koinInject 29 | 30 | val goBack = mutableStateOf(false) 31 | val selectedThemeState = mutableStateOf(Theme.SYSTEM.value) 32 | val isDarkThemeState = mutableStateOf(false) 33 | val isMaterialYouEnabledState = mutableStateOf(true) 34 | 35 | @Composable 36 | fun App(darkTheme: Boolean, dynamicColor: Boolean) { 37 | 38 | val settingsUtils = koinInject() 39 | LaunchedEffect(Unit) { 40 | selectedThemeState.value = settingsUtils.fetchInt(SettingsUtils.THEME, Theme.SYSTEM.value) 41 | isMaterialYouEnabledState.value = 42 | settingsUtils.fetchBoolean(SettingsUtils.IS_MATERIAL_YOU_ENABLED, true) 43 | } 44 | 45 | SplashyTheme( 46 | darkTheme = isDarkThemeState.value, 47 | dynamicColor = if (dynamicColor) isMaterialYouEnabledState.value else false 48 | ) { 49 | Navigator( 50 | screen = TopLevelScreen(), 51 | disposeBehavior = 52 | NavigatorDisposeBehavior(disposeNestedNavigators = false, disposeSteps = true) 53 | ) { 54 | SlideTransition(it) 55 | } 56 | } 57 | 58 | LaunchedEffect(selectedThemeState.value) { 59 | updateTheme(selectedThemeState.value, darkTheme) { isDarkTheme -> 60 | isDarkThemeState.value = isDarkTheme 61 | } 62 | } 63 | } 64 | 65 | fun updateTheme(theme: Int, isSystemDarkTheme: Boolean, onThemeChanged: (Boolean) -> Unit) { 66 | val isDarkTheme = 67 | if (theme == Theme.SYSTEM.value) { 68 | isSystemDarkTheme 69 | } else { 70 | theme == Theme.DARK.value 71 | } 72 | onThemeChanged(isDarkTheme) 73 | } 74 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/di/ApplicationModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.di 17 | 18 | import dev.ishubhamsingh.splashy.core.di.components.commonModule 19 | import dev.ishubhamsingh.splashy.core.di.components.platformModule 20 | 21 | fun appModule() = listOf(platformModule, commonModule) 22 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/di/components/CommonModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.di.components 17 | 18 | import dev.ishubhamsingh.splashy.core.domain.UnsplashRepository 19 | import dev.ishubhamsingh.splashy.core.network.UnsplashRepositoryImpl 20 | import dev.ishubhamsingh.splashy.core.network.api.UnsplashApi 21 | import dev.ishubhamsingh.splashy.core.utils.SettingsUtils 22 | import dev.ishubhamsingh.splashy.core.utils.getHttpClient 23 | import dev.ishubhamsingh.splashy.db.createDatabase 24 | import dev.ishubhamsingh.splashy.features.categories.CategoriesScreenModel 25 | import dev.ishubhamsingh.splashy.features.categoriesPhotos.CategoriesPhotosScreenModel 26 | import dev.ishubhamsingh.splashy.features.favourites.FavouritesScreenModel 27 | import dev.ishubhamsingh.splashy.features.home.HomeScreenModel 28 | import dev.ishubhamsingh.splashy.features.settings.SettingsScreenModel 29 | import org.koin.core.module.dsl.singleOf 30 | import org.koin.dsl.module 31 | 32 | val commonModule = module { 33 | singleOf(::getHttpClient) 34 | single { UnsplashApi(get()) } 35 | single { createDatabase(get()) } 36 | factory { UnsplashRepositoryImpl(get(), get()) } 37 | factory { HomeScreenModel(get(), get()) } 38 | factory { FavouritesScreenModel(get(), get()) } 39 | factory { CategoriesScreenModel(get(), get()) } 40 | factory { CategoriesPhotosScreenModel(get(), get()) } 41 | factory { SettingsScreenModel(get()) } 42 | single { SettingsUtils() } 43 | } 44 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/di/components/PlatformModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.di.components 17 | 18 | import org.koin.core.module.Module 19 | 20 | /** Created by Shubham Singh on 11/08/23. */ 21 | expect val platformModule: Module 22 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/domain/NetworkResult.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.domain 17 | 18 | sealed class NetworkResult( 19 | val data: T? = null, 20 | val message: String? = null, 21 | exception: Exception? = null 22 | ) { 23 | class Success(data: T?) : NetworkResult(data) 24 | 25 | class Error(message: String, exception: Exception? = null) : 26 | NetworkResult(message = message, exception = exception) 27 | 28 | class Loading(val isLoading: Boolean = true) : NetworkResult(null) 29 | } 30 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/domain/ScreenEvent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.domain 17 | 18 | /** Created by Shubham Singh on 12/08/23. */ 19 | interface ScreenEvent 20 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/domain/UnsplashRepository.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.domain 17 | 18 | import dev.ishubhamsingh.splashy.models.CollectionItem 19 | import dev.ishubhamsingh.splashy.models.DownloadUrl 20 | import dev.ishubhamsingh.splashy.models.Favourite 21 | import dev.ishubhamsingh.splashy.models.Photo 22 | import dev.ishubhamsingh.splashy.models.PhotoSearchCollection 23 | import dev.ishubhamsingh.splashy.models.Topic 24 | import kotlinx.coroutines.flow.Flow 25 | 26 | interface UnsplashRepository { 27 | fun getPhotos(page: Int, fetchFromRemote: Boolean = false): Flow>> 28 | 29 | fun searchPhotos( 30 | searchQuery: String, 31 | page: Int, 32 | fetchFromRemote: Boolean = false 33 | ): Flow> 34 | 35 | fun getPhotoDetails(id: String): Flow> 36 | 37 | fun getCollections(page: Int): Flow>> 38 | 39 | fun getCollectionById(id: String): Flow> 40 | 41 | fun getPhotosByCollection(id: String, page: Int): Flow>> 42 | 43 | fun getTopics(page: Int): Flow>> 44 | 45 | fun getTopicBySlug(slug: String): Flow> 46 | 47 | fun getPhotosByTopic(slug: String, page: Int): Flow>> 48 | 49 | fun getDownloadUrl(url: String): Flow> 50 | 51 | fun addFavourite(favourite: Favourite): Flow> 52 | 53 | fun removeFavourite(id: String): Flow> 54 | 55 | fun isFavourite(id: String): Flow> 56 | 57 | fun getFavourites(): Flow>> 58 | } 59 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/navigation/SplashyAppState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.navigation 17 | 18 | import androidx.compose.material3.SnackbarDuration 19 | import androidx.compose.material3.SnackbarHostState 20 | import androidx.compose.runtime.Composable 21 | import androidx.compose.runtime.remember 22 | import androidx.compose.runtime.rememberCoroutineScope 23 | import kotlinx.coroutines.CoroutineScope 24 | import kotlinx.coroutines.launch 25 | 26 | /** Created by Shubham Singh on 30/09/23. */ 27 | data class SplashyAppState( 28 | val snackbarHostState: SnackbarHostState, 29 | val coroutineScope: CoroutineScope, 30 | ) { 31 | 32 | fun showSnackbar(message: String, duration: SnackbarDuration = SnackbarDuration.Short) { 33 | coroutineScope.launch { snackbarHostState.showSnackbar(message = message, duration = duration) } 34 | } 35 | } 36 | 37 | @Composable 38 | fun rememberSplashyAppState( 39 | snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }, 40 | coroutineScope: CoroutineScope = rememberCoroutineScope() 41 | ) = 42 | remember(snackbarHostState, coroutineScope) { 43 | SplashyAppState(snackbarHostState = snackbarHostState, coroutineScope = coroutineScope) 44 | } 45 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/network/KtorLogger.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.network 17 | 18 | import io.github.aakira.napier.Napier 19 | import io.ktor.client.plugins.logging.Logger 20 | 21 | /** Created by Shubham Singh on 05/08/23. */ 22 | class KtorLogger() : Logger { 23 | override fun log(message: String) { 24 | Napier.d(message) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/presentation/SplashyTheme.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.presentation 17 | 18 | import androidx.compose.foundation.isSystemInDarkTheme 19 | import androidx.compose.runtime.Composable 20 | 21 | @Composable 22 | expect fun SplashyTheme( 23 | darkTheme: Boolean = isSystemInDarkTheme(), 24 | dynamicColor: Boolean, 25 | content: @Composable () -> Unit 26 | ) 27 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/utils/CommonUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import androidx.compose.runtime.Composable 19 | import androidx.compose.ui.graphics.Color 20 | import io.ktor.client.HttpClient 21 | 22 | expect fun getHttpClient(): HttpClient 23 | 24 | expect fun getFormattedDateTime(timestamp: String, format: String = "dd MMM yyyy, hh:mm a"): String 25 | 26 | expect fun getPlatform(): Platform 27 | 28 | expect fun isDebug(): Boolean 29 | 30 | @Composable expect fun getScreenHeight(): Int 31 | 32 | enum class Platform { 33 | Android, 34 | iOS 35 | } 36 | 37 | @Composable 38 | expect fun UpdateSystemBars(statusBarColor: Color, navigationBarColor: Color, isDarkTheme: Boolean) 39 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/utils/DIHelper.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import dev.ishubhamsingh.splashy.core.di.appModule 19 | import org.koin.core.context.startKoin 20 | 21 | fun initKoin() { 22 | startKoin { modules(appModule()) } 23 | } 24 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/utils/DatabaseDriverFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import app.cash.sqldelight.db.SqlDriver 19 | 20 | /** Created by Shubham Singh on 11/08/23. */ 21 | internal const val DB_NAME = "splashy.db" 22 | 23 | expect class DatabaseDriverFactory { 24 | fun createDriver(): SqlDriver 25 | } 26 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/utils/Extensions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import dev.ishubhamsingh.splashy.models.CollectionItem 19 | import kotlinx.datetime.Clock 20 | import kotlinx.datetime.Instant 21 | import kotlinx.datetime.LocalDateTime 22 | import kotlinx.datetime.TimeZone 23 | import kotlinx.datetime.toLocalDateTime 24 | 25 | inline fun > Int.toEnum(): T? { 26 | return enumValues().firstOrNull { it.ordinal == this } 27 | } 28 | 29 | fun ArrayList.getNonPremiumCollections(): ArrayList { 30 | val filteredList = 31 | this.filter { it.coverPhoto?.urls?.regular?.contains("plus.unsplash") == false } 32 | return ArrayList(filteredList) 33 | } 34 | 35 | // fun returns true if current device date is in between 22nd December and 5th January 36 | fun isChristmasNewYearWeek(): Boolean { 37 | val currentMoment: Instant = Clock.System.now() 38 | val datetimeInSystemZone: LocalDateTime = 39 | currentMoment.toLocalDateTime(TimeZone.currentSystemDefault()) 40 | val currentMonth = datetimeInSystemZone.monthNumber 41 | val currentDay = datetimeInSystemZone.dayOfMonth 42 | return (currentMonth == 12 && currentDay >= 22) || (currentMonth == 1 && currentDay <= 5) 43 | } 44 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/utils/FileUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import com.eygraber.uri.Uri 19 | import dev.ishubhamsingh.splashy.features.details.WallpaperScreenType 20 | 21 | /** Created by Shubham Singh on 19/08/23. */ 22 | expect class FileUtils { 23 | 24 | suspend fun saveByteArrayToFile( 25 | fileName: String, 26 | data: ByteArray, 27 | shouldOpenFile: Boolean, 28 | updateMessage: (String) -> Unit = {} 29 | ) 30 | 31 | suspend fun openFile(uri: Uri?, fileName: String) 32 | 33 | suspend fun applyWallpaper( 34 | data: ByteArray, 35 | wallpaperScreenType: WallpaperScreenType, 36 | updateMessage: (String) -> Unit = {} 37 | ) 38 | 39 | suspend fun shouldAskStorageRuntimePermission(): Boolean 40 | 41 | suspend fun showMessage(message: String) 42 | } 43 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/utils/Logging.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import io.github.aakira.napier.DebugAntilog 19 | import io.github.aakira.napier.Napier 20 | 21 | fun initialiseLogging() { 22 | if (isDebug()) { 23 | Napier.base(DebugAntilog()) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/core/utils/SettingsUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import com.russhwolf.settings.ObservableSettings 19 | import com.russhwolf.settings.Settings 20 | import dev.ishubhamsingh.splashy.features.settings.Theme 21 | 22 | /** Created by Shubham Singh on 24/11/23. */ 23 | interface KeyValueStorage { 24 | fun storeInt(key: String, value: Int) 25 | 26 | fun storeBoolean(key: String, value: Boolean) 27 | 28 | fun storeFloat(key: String, value: Float) 29 | 30 | fun storeString(key: String, value: String) 31 | 32 | fun fetchString(key: String, default: String = ""): String 33 | 34 | fun fetchBoolean(key: String, default: Boolean): Boolean 35 | 36 | fun fetchInt(key: String, default: Int): Int 37 | 38 | fun fetchFloat(key: String, default: Float): Float 39 | 40 | fun clearStorage() 41 | 42 | fun removeKey(key: String) 43 | } 44 | 45 | class SettingsUtils(private val settings: Settings = Settings()) : KeyValueStorage { 46 | 47 | fun addListener( 48 | mSettings: ObservableSettings = settings as ObservableSettings, 49 | key: String, 50 | defaultValue: Int, 51 | callback: (Int?) -> Unit 52 | ) { 53 | mSettings.addIntListener(key, defaultValue) { newValue -> callback(newValue) } 54 | } 55 | 56 | override fun storeInt(key: String, value: Int) { 57 | settings.putInt(key, value) 58 | } 59 | 60 | override fun storeBoolean(key: String, value: Boolean) { 61 | settings.putBoolean(key, value) 62 | } 63 | 64 | override fun storeFloat(key: String, value: Float) { 65 | settings.putFloat(key, value) 66 | } 67 | 68 | override fun storeString(key: String, value: String) { 69 | settings.putString(key, value) 70 | } 71 | 72 | override fun fetchString(key: String, default: String): String { 73 | return settings.getString(key, default) 74 | } 75 | 76 | override fun fetchBoolean(key: String, default: Boolean): Boolean { 77 | return settings.getBoolean(key, default) 78 | } 79 | 80 | override fun fetchInt(key: String, default: Int): Int { 81 | return settings.getInt(key, default) 82 | } 83 | 84 | override fun fetchFloat(key: String, default: Float): Float { 85 | return settings.getFloat(key, default) 86 | } 87 | 88 | override fun clearStorage() { 89 | settings.clear() 90 | } 91 | 92 | override fun removeKey(key: String) { 93 | settings.remove(key) 94 | } 95 | 96 | companion object { 97 | const val THEME = "theme" 98 | const val IS_MATERIAL_YOU_ENABLED = "is_material_you_enabled" 99 | } 100 | 101 | fun isDarkTheme(isSystemDarkTheme: Boolean): Boolean { 102 | val currentTheme = fetchInt(THEME, Theme.SYSTEM.value) 103 | 104 | return if (currentTheme == Theme.SYSTEM.value) { 105 | isSystemDarkTheme 106 | } else { 107 | currentTheme == Theme.DARK.value 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/db/Database.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.db 17 | 18 | import dev.ishubhamsingh.splashy.core.utils.DatabaseDriverFactory 19 | import dev.ishubhamsingh.splashy.db.columnAdapters.IntAdapter 20 | import dev.ishubhamsingh.splashy.db.columnAdapters.LinksAdapter 21 | import dev.ishubhamsingh.splashy.db.columnAdapters.TopicSubmissionsAdapter 22 | import dev.ishubhamsingh.splashy.db.columnAdapters.UrlsAdapter 23 | import dev.ishubhamsingh.splashy.db.columnAdapters.UserAdapter 24 | 25 | /** Created by Shubham Singh on 11/08/23. */ 26 | fun createDatabase(databaseDriverFactory: DatabaseDriverFactory): SplashyDatabase { 27 | val driver = databaseDriverFactory.createDriver() 28 | 29 | return SplashyDatabase( 30 | driver = driver, 31 | photoEntityAdapter = 32 | PhotoEntity.Adapter( 33 | linksAdapter = LinksAdapter, 34 | topicSubmissionsAdapter = TopicSubmissionsAdapter, 35 | urlsAdapter = UrlsAdapter, 36 | userAdapter = UserAdapter, 37 | heightAdapter = IntAdapter, 38 | widthAdapter = IntAdapter, 39 | likesAdapter = IntAdapter 40 | ), 41 | favouriteEntityAdapter = 42 | FavouriteEntity.Adapter(topicSubmissionsAdapter = TopicSubmissionsAdapter) 43 | ) 44 | } 45 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/db/columnAdapters/IntAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.db.columnAdapters 17 | 18 | import app.cash.sqldelight.ColumnAdapter 19 | 20 | /** Created by Shubham Singh on 11/08/23. */ 21 | object IntAdapter : ColumnAdapter { 22 | override fun decode(databaseValue: Long): Int { 23 | return databaseValue.toInt() 24 | } 25 | 26 | override fun encode(value: Int): Long { 27 | return value.toLong() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/db/columnAdapters/LinksAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.db.columnAdapters 17 | 18 | import app.cash.sqldelight.ColumnAdapter 19 | import dev.ishubhamsingh.splashy.models.Links 20 | import kotlinx.serialization.json.Json 21 | 22 | /** Created by Shubham Singh on 11/08/23. */ 23 | object LinksAdapter : ColumnAdapter { 24 | override fun decode(databaseValue: String): Links { 25 | return Json.decodeFromString(databaseValue) 26 | } 27 | 28 | override fun encode(value: Links): String { 29 | return value.toString() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/db/columnAdapters/TopicSubmissionsAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.db.columnAdapters 17 | 18 | import app.cash.sqldelight.ColumnAdapter 19 | import dev.ishubhamsingh.splashy.models.TopicSubmissions 20 | import kotlinx.serialization.json.Json 21 | 22 | /** Created by Shubham Singh on 11/08/23. */ 23 | object TopicSubmissionsAdapter : ColumnAdapter { 24 | override fun decode(databaseValue: String): TopicSubmissions { 25 | return Json.decodeFromString(databaseValue) 26 | } 27 | 28 | override fun encode(value: TopicSubmissions): String { 29 | return value.toString() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/db/columnAdapters/UrlsAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.db.columnAdapters 17 | 18 | import app.cash.sqldelight.ColumnAdapter 19 | import dev.ishubhamsingh.splashy.models.Urls 20 | import kotlinx.serialization.json.Json 21 | 22 | /** Created by Shubham Singh on 11/08/23. */ 23 | object UrlsAdapter : ColumnAdapter { 24 | override fun decode(databaseValue: String): Urls { 25 | return Json.decodeFromString(databaseValue) 26 | } 27 | 28 | override fun encode(value: Urls): String { 29 | return value.toString() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/db/columnAdapters/UserAdapter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.db.columnAdapters 17 | 18 | import app.cash.sqldelight.ColumnAdapter 19 | import dev.ishubhamsingh.splashy.models.User 20 | import kotlinx.serialization.json.Json 21 | 22 | /** Created by Shubham Singh on 11/08/23. */ 23 | object UserAdapter : ColumnAdapter { 24 | override fun decode(databaseValue: String): User { 25 | return Json.decodeFromString(databaseValue) 26 | } 27 | 28 | override fun encode(value: User): String { 29 | return value.toString() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/db/mappers/FavouriteMapper.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.db.mappers 17 | 18 | import dev.ishubhamsingh.splashy.db.FavouriteEntity 19 | import dev.ishubhamsingh.splashy.models.Favourite 20 | import dev.ishubhamsingh.splashy.models.Photo 21 | 22 | /** Created by Shubham Singh on 12/08/23. */ 23 | fun Photo.toFavourite(): Favourite = 24 | Favourite( 25 | id = id, 26 | color = color, 27 | altDescription = altDescription, 28 | description = description, 29 | topicSubmissions = topicSubmissions, 30 | url = urls?.regular 31 | ) 32 | 33 | fun Favourite.toFavouriteEntity(): FavouriteEntity = 34 | FavouriteEntity( 35 | id = id, 36 | color = color, 37 | altDescription = altDescription, 38 | description = description, 39 | topicSubmissions = topicSubmissions, 40 | url = url 41 | ) 42 | 43 | fun FavouriteEntity.toFavourite(): Favourite = 44 | Favourite( 45 | id = id, 46 | color = color, 47 | altDescription = altDescription, 48 | description = description, 49 | topicSubmissions = topicSubmissions, 50 | url = url 51 | ) 52 | 53 | fun List.toFavouriteList(): List = map { it.toFavourite() } 54 | 55 | fun List.toFavouriteArrayList(): ArrayList = 56 | ArrayList(toFavouriteList()) 57 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/db/mappers/PhotoMapper.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.db.mappers 17 | 18 | import dev.ishubhamsingh.splashy.db.PhotoEntity 19 | import dev.ishubhamsingh.splashy.models.Photo 20 | import dev.ishubhamsingh.splashy.models.PhotoSearchCollection 21 | 22 | /** Created by Shubham Singh on 11/08/23. */ 23 | fun PhotoEntity.toPhoto(): Photo = 24 | Photo( 25 | id = id, 26 | altDescription = altDescription ?: "", 27 | color = color ?: "", 28 | description = description ?: "", 29 | width = width ?: 0, 30 | height = height ?: 0, 31 | likes = likes ?: 0, 32 | user = user, 33 | urls = urls, 34 | links = links, 35 | topicSubmissions = topicSubmissions, 36 | createdAt = createdAt, 37 | updatedAt = updatedAt, 38 | promotedAt = promotedAt 39 | ) 40 | 41 | fun Photo.toPhotoEntity(): PhotoEntity = 42 | PhotoEntity( 43 | id = id, 44 | altDescription = altDescription, 45 | color = color, 46 | description = description, 47 | width = width, 48 | height = height, 49 | likes = likes, 50 | user = user, 51 | urls = urls, 52 | links = links, 53 | topicSubmissions = topicSubmissions, 54 | createdAt = createdAt, 55 | updatedAt = updatedAt, 56 | promotedAt = promotedAt 57 | ) 58 | 59 | fun List.toPhotoList(): List = map { it.toPhoto() } 60 | 61 | fun List.toPhotoEntityList(): List = map { it.toPhotoEntity() } 62 | 63 | fun List.toPhotoArrayList(): ArrayList = ArrayList(toPhotoList()) 64 | 65 | fun ArrayList.toPhotoSearchCollection(): PhotoSearchCollection = 66 | PhotoSearchCollection(results = this, total = this.size, totalPages = this.size / 10) 67 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/about/ui/AboutComponent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.about.ui 17 | 18 | class AboutComponent {} 19 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/categories/CategoriesScreenModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.categories 17 | 18 | import cafe.adriel.voyager.core.model.ScreenModel 19 | import cafe.adriel.voyager.core.model.screenModelScope 20 | import dev.ishubhamsingh.splashy.core.domain.NetworkResult 21 | import dev.ishubhamsingh.splashy.core.domain.UnsplashRepository 22 | import dev.ishubhamsingh.splashy.core.utils.SettingsUtils 23 | import dev.ishubhamsingh.splashy.features.categories.ui.CategoriesEvent 24 | import dev.ishubhamsingh.splashy.features.categories.ui.CategoriesState 25 | import io.github.aakira.napier.Napier 26 | import kotlinx.coroutines.flow.MutableStateFlow 27 | import kotlinx.coroutines.flow.asStateFlow 28 | import kotlinx.coroutines.flow.update 29 | import kotlinx.coroutines.launch 30 | 31 | /** Created by Shubham Singh on 30/08/23. */ 32 | class CategoriesScreenModel( 33 | private val unsplashRepository: UnsplashRepository, 34 | val settingsUtils: SettingsUtils 35 | ) : ScreenModel { 36 | 37 | private val _state = MutableStateFlow(CategoriesState()) 38 | val state = _state.asStateFlow() 39 | 40 | init { 41 | onEvent(CategoriesEvent.Load) 42 | } 43 | 44 | fun onEvent(event: CategoriesEvent) { 45 | when (event) { 46 | CategoriesEvent.Refresh, 47 | CategoriesEvent.Load -> { 48 | fetchTopics() 49 | fetchCollections() 50 | } 51 | } 52 | } 53 | 54 | private fun fetchCollections() { 55 | screenModelScope.launch { 56 | unsplashRepository.getCollections(1).collect { networkResult -> 57 | when (networkResult) { 58 | is NetworkResult.Error -> { 59 | networkResult.message?.let { 60 | _state.update { categoriesState -> categoriesState.copy(networkError = it) } 61 | } 62 | Napier.e(networkResult.message.toString()) 63 | } 64 | is NetworkResult.Loading -> { 65 | _state.update { detailsState -> 66 | detailsState.copy(isCollectionsLoading = networkResult.isLoading) 67 | } 68 | } 69 | is NetworkResult.Success -> { 70 | networkResult.data?.let { 71 | _state.update { categoriesState -> categoriesState.copy(collections = it) } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } 78 | 79 | private fun fetchTopics() { 80 | screenModelScope.launch { 81 | unsplashRepository.getTopics(1).collect { networkResult -> 82 | when (networkResult) { 83 | is NetworkResult.Error -> { 84 | networkResult.message?.let { 85 | _state.update { categoriesState -> categoriesState.copy(networkError = it) } 86 | } 87 | Napier.e(networkResult.message.toString()) 88 | } 89 | is NetworkResult.Loading -> { 90 | _state.update { detailsState -> 91 | detailsState.copy(isTopicsLoading = networkResult.isLoading) 92 | } 93 | } 94 | is NetworkResult.Success -> { 95 | networkResult.data?.let { 96 | _state.update { categoriesState -> categoriesState.copy(topics = it) } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/categories/ui/CategoriesEvent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.categories.ui 17 | 18 | /** Created by Shubham Singh on 30/08/23. */ 19 | sealed class CategoriesEvent { 20 | data object Refresh : CategoriesEvent() 21 | 22 | data object Load : CategoriesEvent() 23 | } 24 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/categories/ui/CategoriesState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.categories.ui 17 | 18 | import dev.ishubhamsingh.splashy.models.CollectionItem 19 | import dev.ishubhamsingh.splashy.models.Topic 20 | 21 | /** Created by Shubham Singh on 30/08/23. */ 22 | data class CategoriesState( 23 | val isTopicsLoading: Boolean = false, 24 | val isCollectionsLoading: Boolean = false, 25 | val collections: ArrayList = arrayListOf(), 26 | val topics: ArrayList = arrayListOf(), 27 | val networkError: String? = null 28 | ) { 29 | val isCategoriesLoading: Boolean 30 | get() = isCollectionsLoading && isTopicsLoading 31 | } 32 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/categoriesPhotos/ui/CategoriesPhotosEvent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.categoriesPhotos.ui 17 | 18 | sealed class CategoriesPhotosEvent { 19 | data class Load(val id: String, val type: CategoryType) : CategoriesPhotosEvent() 20 | 21 | data object Refresh : CategoriesPhotosEvent() 22 | 23 | data object LoadMore : CategoriesPhotosEvent() 24 | } 25 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/categoriesPhotos/ui/CategoriesPhotosScreen.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.categoriesPhotos.ui 17 | 18 | import androidx.compose.foundation.clickable 19 | import androidx.compose.foundation.layout.Box 20 | import androidx.compose.foundation.layout.padding 21 | import androidx.compose.material3.ExperimentalMaterial3Api 22 | import androidx.compose.material3.Icon 23 | import androidx.compose.material3.MaterialTheme 24 | import androidx.compose.material3.Scaffold 25 | import androidx.compose.material3.Text 26 | import androidx.compose.material3.TopAppBar 27 | import androidx.compose.material3.TopAppBarDefaults 28 | import androidx.compose.runtime.Composable 29 | import androidx.compose.runtime.LaunchedEffect 30 | import androidx.compose.runtime.collectAsState 31 | import androidx.compose.runtime.getValue 32 | import androidx.compose.ui.Modifier 33 | import androidx.compose.ui.graphics.Color 34 | import androidx.compose.ui.text.style.TextOverflow 35 | import cafe.adriel.voyager.core.screen.Screen 36 | import cafe.adriel.voyager.koin.getScreenModel 37 | import cafe.adriel.voyager.navigator.LocalNavigator 38 | import cafe.adriel.voyager.navigator.currentOrThrow 39 | import compose.icons.EvaIcons 40 | import compose.icons.evaicons.Outline 41 | import compose.icons.evaicons.outline.ArrowIosBack 42 | import dev.ishubhamsingh.splashy.core.utils.UpdateSystemBars 43 | import dev.ishubhamsingh.splashy.core.utils.isChristmasNewYearWeek 44 | import dev.ishubhamsingh.splashy.features.categoriesPhotos.CategoriesPhotosScreenModel 45 | import dev.ishubhamsingh.splashy.features.details.ui.DetailsScreen 46 | import dev.ishubhamsingh.splashy.goBack 47 | import dev.ishubhamsingh.splashy.isDarkThemeState 48 | import dev.ishubhamsingh.splashy.models.Photo 49 | import dev.ishubhamsingh.splashy.ui.components.GoBack 50 | import dev.ishubhamsingh.splashy.ui.components.PhotoGridLayout 51 | import dev.ishubhamsingh.splashy.ui.components.SnowFallComponent 52 | 53 | data class CategoriesPhotosScreen( 54 | val id: String, 55 | val categoryType: CategoryType, 56 | val name: String 57 | ) : Screen { 58 | 59 | @OptIn(ExperimentalMaterial3Api::class) 60 | @Composable 61 | override fun Content() { 62 | val screenModel = getScreenModel() 63 | UpdateSystemBars( 64 | statusBarColor = Color.Transparent, 65 | navigationBarColor = Color.Transparent, 66 | isDarkTheme = isDarkThemeState.value 67 | ) 68 | val navigator = LocalNavigator.currentOrThrow 69 | val state by screenModel.state.collectAsState() 70 | 71 | LaunchedEffect(Unit) { screenModel.onEvent(CategoriesPhotosEvent.Load(id, categoryType)) } 72 | 73 | Scaffold( 74 | topBar = { 75 | Box { 76 | TopAppBar( 77 | title = { 78 | Text( 79 | text = name, 80 | style = MaterialTheme.typography.titleLarge, 81 | maxLines = 1, 82 | overflow = TextOverflow.Ellipsis 83 | ) 84 | }, 85 | navigationIcon = { 86 | Icon( 87 | imageVector = EvaIcons.Outline.ArrowIosBack, 88 | contentDescription = "back", 89 | modifier = Modifier.clickable { navigator.pop() } 90 | ) 91 | }, 92 | colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent) 93 | ) 94 | if (isChristmasNewYearWeek()) { 95 | SnowFallComponent() 96 | } 97 | } 98 | } 99 | ) { paddingValues -> 100 | PhotoGridLayout( 101 | isRefreshing = state.isRefreshing, 102 | onRefresh = { screenModel.onEvent(CategoriesPhotosEvent.Refresh) }, 103 | onSurfaceTouch = {}, 104 | isPaginating = state.isPaginating, 105 | photos = state.photos, 106 | onLoadMore = { 107 | if (state.totalPages > state.currentPage) { 108 | screenModel.onEvent(CategoriesPhotosEvent.LoadMore) 109 | } 110 | }, 111 | onItemSelected = { 112 | photo: Photo?, 113 | id: String?, 114 | color: String?, 115 | url: String?, 116 | altDescription: String? -> 117 | navigator.push( 118 | DetailsScreen( 119 | photo = photo, 120 | id = id, 121 | color = color, 122 | url = url, 123 | altDescription = altDescription 124 | ) 125 | ) 126 | }, 127 | error = state.networkError, 128 | shouldShowSearch = false, 129 | modifier = Modifier.padding(paddingValues) 130 | ) 131 | } 132 | 133 | if (goBack.value) { 134 | GoBack(navigator) 135 | goBack.value = false 136 | } 137 | } 138 | } 139 | 140 | enum class CategoryType { 141 | COLLECTION, 142 | TOPIC 143 | } 144 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/categoriesPhotos/ui/CategoriesPhotosState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.categoriesPhotos.ui 17 | 18 | import dev.ishubhamsingh.splashy.models.CollectionItem 19 | import dev.ishubhamsingh.splashy.models.Photo 20 | import dev.ishubhamsingh.splashy.models.Topic 21 | 22 | data class CategoriesPhotosState( 23 | val id: String? = null, 24 | val isRefreshing: Boolean = false, 25 | val photos: ArrayList = arrayListOf(), 26 | val topic: Topic? = null, 27 | val collection: CollectionItem? = null, 28 | val networkError: String? = null, 29 | val isPaginating: Boolean = false, 30 | val currentPage: Int = 1, 31 | val totalPages: Int = 0, 32 | val categoryType: CategoryType? = null 33 | ) 34 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/details/ui/DetailsEvent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.details.ui 17 | 18 | import dev.ishubhamsingh.splashy.core.domain.ScreenEvent 19 | import dev.ishubhamsingh.splashy.features.details.WallpaperScreenType 20 | import dev.ishubhamsingh.splashy.models.Photo 21 | 22 | sealed class DetailsEvent : ScreenEvent { 23 | data class LoadDetails( 24 | val photo: Photo?, 25 | val id: String?, 26 | val color: String?, 27 | val url: String?, 28 | val altDescription: String? 29 | ) : DetailsEvent() 30 | 31 | data object DownloadPhoto : DetailsEvent() 32 | 33 | data class ApplyAsWallpaper(val wallpaperScreenType: WallpaperScreenType) : DetailsEvent() 34 | 35 | data object ShowApplyWallpaperDialog : DetailsEvent() 36 | 37 | data object DismissApplyWallpaperDialog : DetailsEvent() 38 | 39 | data object AddFavourite : DetailsEvent() 40 | 41 | data object RemoveFavourite : DetailsEvent() 42 | } 43 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/details/ui/DetailsState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.details.ui 17 | 18 | import dev.ishubhamsingh.splashy.models.Photo 19 | 20 | data class DetailsState( 21 | val id: String? = null, 22 | val color: String? = null, 23 | val altDescription: String? = null, 24 | val url: String? = null, 25 | val photo: Photo? = null, 26 | val isFavourite: Boolean = false, 27 | val isLoading: Boolean = false, 28 | val isDownloading: Boolean = false, 29 | val isApplying: Boolean = false, 30 | val networkError: String? = null, 31 | val snackBarMessage: String? = null, 32 | val shouldShowApplyWallpaperDialog: Boolean = false, 33 | val downloadProgress: Int = 0 34 | ) 35 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/favourites/FavouritesScreenModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.favourites 17 | 18 | import cafe.adriel.voyager.core.model.ScreenModel 19 | import cafe.adriel.voyager.core.model.screenModelScope 20 | import dev.ishubhamsingh.splashy.core.domain.NetworkResult 21 | import dev.ishubhamsingh.splashy.core.domain.UnsplashRepository 22 | import dev.ishubhamsingh.splashy.core.utils.SettingsUtils 23 | import dev.ishubhamsingh.splashy.features.favourites.ui.FavouritesEvent 24 | import dev.ishubhamsingh.splashy.features.favourites.ui.FavouritesState 25 | import dev.ishubhamsingh.splashy.models.TopicFilter 26 | import dev.ishubhamsingh.splashy.models.TopicSubmissions 27 | import kotlinx.coroutines.Job 28 | import kotlinx.coroutines.flow.MutableStateFlow 29 | import kotlinx.coroutines.flow.asStateFlow 30 | import kotlinx.coroutines.flow.update 31 | import kotlinx.coroutines.launch 32 | 33 | /** Created by Shubham Singh on 12/08/23. */ 34 | class FavouritesScreenModel( 35 | private val unsplashRepository: UnsplashRepository, 36 | val settingsUtils: SettingsUtils 37 | ) : ScreenModel { 38 | 39 | private val _state = MutableStateFlow(FavouritesState()) 40 | val state = _state.asStateFlow() 41 | 42 | private var job: Job? = null 43 | 44 | fun onEvent(favouritesEvent: FavouritesEvent) { 45 | when (favouritesEvent) { 46 | is FavouritesEvent.Filter -> onFilterEvent(favouritesEvent.topic) 47 | FavouritesEvent.LoadFavourites -> fetchFavourites() 48 | FavouritesEvent.Refresh -> { 49 | _state.update { favouritesState -> 50 | favouritesState.copy(filterTopics = TopicSubmissions.TOPICS) 51 | } 52 | fetchFavourites() 53 | } 54 | } 55 | } 56 | 57 | private fun fetchFavourites() { 58 | cancelActiveJob() 59 | job = 60 | screenModelScope.launch { 61 | unsplashRepository.getFavourites().collect { result -> 62 | when (result) { 63 | is NetworkResult.Error -> { 64 | _state.update { favouritesState -> favouritesState.copy(error = result.message) } 65 | } 66 | is NetworkResult.Loading -> { 67 | _state.update { favouritesState -> 68 | favouritesState.copy(isRefreshing = result.isLoading) 69 | } 70 | } 71 | is NetworkResult.Success -> { 72 | result.data?.let { 73 | _state.update { favouritesState -> favouritesState.copy(favourites = it) } 74 | updateFilteredList(state.value.filterTopics) 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | 82 | private fun onFilterEvent(topic: String) { 83 | val newFilterTopics = 84 | ArrayList( 85 | state.value.filterTopics.map { 86 | if (it.topic == topic) { 87 | TopicFilter(topic, !it.isSelected) 88 | } else { 89 | it 90 | } 91 | } 92 | ) 93 | 94 | _state.update { favouritesState -> favouritesState.copy(filterTopics = newFilterTopics) } 95 | 96 | updateFilteredList(newFilterTopics) 97 | } 98 | 99 | private fun updateFilteredList(newFilterTopics: ArrayList) { 100 | val newFilteredFav = 101 | state.value.favourites.filter { fav -> 102 | fav.topicSubmissions?.containsAnyTopic(newFilterTopics) == true 103 | } 104 | _state.update { favouritesState -> 105 | favouritesState.copy(filteredFavourites = ArrayList(newFilteredFav)) 106 | } 107 | } 108 | 109 | private fun cancelActiveJob() { 110 | if (job?.isActive == true) { 111 | job?.cancel() 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/favourites/ui/FavouritesEvent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.favourites.ui 17 | 18 | import dev.ishubhamsingh.splashy.core.domain.ScreenEvent 19 | 20 | /** Created by Shubham Singh on 12/08/23. */ 21 | sealed class FavouritesEvent : ScreenEvent { 22 | data object LoadFavourites : FavouritesEvent() 23 | 24 | data class Filter(val topic: String) : FavouritesEvent() 25 | 26 | data object Refresh : FavouritesEvent() 27 | } 28 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/favourites/ui/FavouritesState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.favourites.ui 17 | 18 | import dev.ishubhamsingh.splashy.models.Favourite 19 | import dev.ishubhamsingh.splashy.models.TopicFilter 20 | import dev.ishubhamsingh.splashy.models.TopicSubmissions 21 | 22 | /** Created by Shubham Singh on 12/08/23. */ 23 | data class FavouritesState( 24 | val favourites: ArrayList = arrayListOf(), 25 | val filterTopics: ArrayList = TopicSubmissions.TOPICS, 26 | val filteredFavourites: ArrayList = arrayListOf(), 27 | val isRefreshing: Boolean = false, 28 | val error: String? = null 29 | ) 30 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/home/HomeScreenModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.home 17 | 18 | import cafe.adriel.voyager.core.model.ScreenModel 19 | import cafe.adriel.voyager.core.model.screenModelScope 20 | import dev.ishubhamsingh.splashy.core.domain.NetworkResult 21 | import dev.ishubhamsingh.splashy.core.domain.UnsplashRepository 22 | import dev.ishubhamsingh.splashy.core.utils.SettingsUtils 23 | import dev.ishubhamsingh.splashy.features.home.ui.HomeEvent 24 | import dev.ishubhamsingh.splashy.features.home.ui.HomeState 25 | import kotlinx.coroutines.Dispatchers 26 | import kotlinx.coroutines.IO 27 | import kotlinx.coroutines.Job 28 | import kotlinx.coroutines.flow.MutableStateFlow 29 | import kotlinx.coroutines.flow.asStateFlow 30 | import kotlinx.coroutines.flow.update 31 | import kotlinx.coroutines.launch 32 | 33 | class HomeScreenModel( 34 | private val unsplashRepository: UnsplashRepository, 35 | val settingsUtils: SettingsUtils 36 | ) : ScreenModel { 37 | 38 | private val _state = MutableStateFlow(HomeState()) 39 | val state = _state.asStateFlow() 40 | 41 | private var job: Job? = null 42 | 43 | init { 44 | onEvent(HomeEvent.Load) 45 | } 46 | 47 | fun onEvent(event: HomeEvent) { 48 | when (event) { 49 | HomeEvent.Load -> { 50 | getPhotosFromApi(forceFetch = true) 51 | } 52 | HomeEvent.Refresh -> { 53 | resetPage() 54 | getPhotosFromApi(forceFetch = true) 55 | } 56 | is HomeEvent.OnSearchQueryChange -> { 57 | _state.update { homeState -> homeState.copy(searchQuery = event.query) } 58 | resetPage(false) 59 | getPhotosFromApi(loadingType = LoadingType.SEARCH, forceFetch = true) 60 | } 61 | HomeEvent.LoadMore -> { 62 | nextPage() 63 | getPhotosFromApi(loadingType = LoadingType.PAGINATION, forceFetch = true) 64 | } 65 | } 66 | } 67 | 68 | private fun nextPage() { 69 | _state.update { it.copy(currentPage = it.currentPage + 1) } 70 | } 71 | 72 | private fun resetPage(isResetQuery: Boolean = true) { 73 | _state.update { 74 | if (isResetQuery) { 75 | it.copy(currentPage = 1, totalPages = 0, searchQuery = null, photos = arrayListOf()) 76 | } else { 77 | it.copy(currentPage = 1, totalPages = 0, photos = arrayListOf()) 78 | } 79 | } 80 | } 81 | 82 | private fun getPhotosFromApi( 83 | loadingType: LoadingType = LoadingType.REFRESH, 84 | forceFetch: Boolean = false 85 | ) { 86 | if (state.value.searchQuery.isNullOrEmpty().not()) { 87 | searchPhotos(loadingType = loadingType, forceFetch = forceFetch) 88 | } else { 89 | fetchPhotos(loadingType = loadingType, forceFetch = forceFetch) 90 | } 91 | } 92 | 93 | private fun searchPhotos( 94 | page: Int = state.value.currentPage, 95 | loadingType: LoadingType = LoadingType.REFRESH, 96 | forceFetch: Boolean = false 97 | ) { 98 | cancelActiveJob() // Cancel ongoing call before launching new 99 | job = 100 | screenModelScope.launch(Dispatchers.IO) { 101 | unsplashRepository 102 | .searchPhotos( 103 | if (state.value.searchQuery.isNullOrEmpty()) "wallpaper" else state.value.searchQuery!!, 104 | page, 105 | forceFetch 106 | ) 107 | .collect { networkResult -> 108 | when (networkResult) { 109 | is NetworkResult.Success -> { 110 | networkResult.data?.let { resp -> 111 | _state.update { homeState -> 112 | val current = homeState.photos 113 | current.addAll(resp.results) 114 | homeState.copy(photos = current, totalPages = resp.totalPages) 115 | } 116 | } 117 | } 118 | is NetworkResult.Error -> { 119 | _state.update { homeState -> homeState.copy(networkError = networkResult.message) } 120 | } 121 | is NetworkResult.Loading -> { 122 | _state.update { homeState -> 123 | when (loadingType) { 124 | LoadingType.REFRESH -> homeState.copy(isRefreshing = networkResult.isLoading) 125 | LoadingType.PAGINATION -> homeState.copy(isPaginating = networkResult.isLoading) 126 | LoadingType.SEARCH -> homeState.copy(isSearching = networkResult.isLoading) 127 | } 128 | } 129 | } 130 | } 131 | } 132 | } 133 | } 134 | 135 | private fun fetchPhotos( 136 | page: Int = state.value.currentPage, 137 | loadingType: LoadingType = LoadingType.REFRESH, 138 | forceFetch: Boolean = false 139 | ) { 140 | cancelActiveJob() // Cancel ongoing call before launching new 141 | job = 142 | screenModelScope.launch(Dispatchers.IO) { 143 | unsplashRepository.getPhotos(page, forceFetch).collect { networkResult -> 144 | when (networkResult) { 145 | is NetworkResult.Success -> { 146 | networkResult.data?.let { resp -> 147 | _state.update { homeState -> 148 | val current = homeState.photos 149 | current.addAll(resp) 150 | homeState.copy(photos = current, totalPages = 1000) 151 | } 152 | } 153 | } 154 | is NetworkResult.Error -> { 155 | _state.update { homeState -> homeState.copy(networkError = networkResult.message) } 156 | } 157 | is NetworkResult.Loading -> { 158 | _state.update { homeState -> 159 | when (loadingType) { 160 | LoadingType.REFRESH -> homeState.copy(isRefreshing = networkResult.isLoading) 161 | LoadingType.PAGINATION -> homeState.copy(isPaginating = networkResult.isLoading) 162 | LoadingType.SEARCH -> homeState.copy(isSearching = networkResult.isLoading) 163 | } 164 | } 165 | } 166 | } 167 | } 168 | } 169 | } 170 | 171 | private fun cancelActiveJob() { 172 | if (job?.isActive == true) { 173 | job?.cancel() 174 | } 175 | } 176 | } 177 | 178 | enum class LoadingType { 179 | REFRESH, 180 | SEARCH, 181 | PAGINATION 182 | } 183 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/home/ui/HomeEvent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.home.ui 17 | 18 | import dev.ishubhamsingh.splashy.core.domain.ScreenEvent 19 | 20 | sealed class HomeEvent : ScreenEvent { 21 | data object Load : HomeEvent() 22 | 23 | data object Refresh : HomeEvent() 24 | 25 | data object LoadMore : HomeEvent() 26 | 27 | data class OnSearchQueryChange(val query: String?) : HomeEvent() 28 | } 29 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/home/ui/HomeState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.home.ui 17 | 18 | import dev.ishubhamsingh.splashy.models.Photo 19 | 20 | data class HomeState( 21 | val photos: ArrayList = arrayListOf(), 22 | val networkError: String? = null, 23 | val isRefreshing: Boolean = false, 24 | val isPaginating: Boolean = false, 25 | val isSearching: Boolean = false, 26 | val searchQuery: String? = null, 27 | val currentPage: Int = 1, 28 | val totalPages: Int = 0 29 | ) 30 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/home/ui/HomeTab.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.home.ui 17 | 18 | import androidx.compose.runtime.Composable 19 | import androidx.compose.runtime.collectAsState 20 | import androidx.compose.runtime.getValue 21 | import androidx.compose.runtime.remember 22 | import androidx.compose.ui.graphics.Color 23 | import androidx.compose.ui.graphics.vector.rememberVectorPainter 24 | import androidx.compose.ui.platform.LocalFocusManager 25 | import cafe.adriel.voyager.koin.getScreenModel 26 | import cafe.adriel.voyager.navigator.LocalNavigator 27 | import cafe.adriel.voyager.navigator.currentOrThrow 28 | import cafe.adriel.voyager.navigator.tab.LocalTabNavigator 29 | import cafe.adriel.voyager.navigator.tab.Tab 30 | import cafe.adriel.voyager.navigator.tab.TabOptions 31 | import compose.icons.EvaIcons 32 | import compose.icons.evaicons.Fill 33 | import compose.icons.evaicons.Outline 34 | import compose.icons.evaicons.fill.Home 35 | import compose.icons.evaicons.outline.Home 36 | import dev.ishubhamsingh.splashy.core.utils.UpdateSystemBars 37 | import dev.ishubhamsingh.splashy.features.details.ui.DetailsScreen 38 | import dev.ishubhamsingh.splashy.features.home.HomeScreenModel 39 | import dev.ishubhamsingh.splashy.isDarkThemeState 40 | import dev.ishubhamsingh.splashy.models.Photo 41 | import dev.ishubhamsingh.splashy.resources.Res 42 | import dev.ishubhamsingh.splashy.resources.lbl_home 43 | import dev.ishubhamsingh.splashy.ui.components.PhotoGridLayout 44 | import org.jetbrains.compose.resources.stringResource 45 | 46 | /** Created by Shubham Singh on 29/09/23. */ 47 | object HomeTab : Tab { 48 | 49 | override val options: TabOptions 50 | @Composable 51 | get() { 52 | val isSelected = LocalTabNavigator.current.current == this 53 | val title = stringResource(Res.string.lbl_home) 54 | val icon = 55 | rememberVectorPainter(if (isSelected) EvaIcons.Fill.Home else EvaIcons.Outline.Home) 56 | 57 | return remember { TabOptions(index = 0u, title, icon) } 58 | } 59 | 60 | @Composable 61 | override fun Content() { 62 | val screenModel = getScreenModel() 63 | UpdateSystemBars( 64 | statusBarColor = Color.Transparent, 65 | navigationBarColor = Color.Transparent, 66 | isDarkTheme = isDarkThemeState.value 67 | ) 68 | val navigator = LocalNavigator.currentOrThrow.parent 69 | val state by screenModel.state.collectAsState() 70 | val focusManager = LocalFocusManager.current 71 | 72 | PhotoGridLayout( 73 | isRefreshing = state.isRefreshing, 74 | onRefresh = { screenModel.onEvent(HomeEvent.Refresh) }, 75 | onSurfaceTouch = { focusManager.clearFocus() }, 76 | searchQuery = state.searchQuery, 77 | isSearching = state.isSearching, 78 | onSearchQueryChange = { screenModel.onEvent(HomeEvent.OnSearchQueryChange(it)) }, 79 | isPaginating = state.isPaginating, 80 | photos = state.photos, 81 | onLoadMore = { 82 | if (state.totalPages > state.currentPage) { 83 | screenModel.onEvent(HomeEvent.LoadMore) 84 | } 85 | }, 86 | onItemSelected = { 87 | photo: Photo?, 88 | id: String?, 89 | color: String?, 90 | url: String?, 91 | altDescription: String? -> 92 | navigator?.push( 93 | DetailsScreen( 94 | photo = photo, 95 | id = id, 96 | color = color, 97 | url = url, 98 | altDescription = altDescription 99 | ) 100 | ) 101 | }, 102 | error = state.networkError, 103 | shouldShowSearch = true 104 | ) 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/settings/SettingsScreenModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.settings 17 | 18 | import cafe.adriel.voyager.core.model.ScreenModel 19 | import dev.ishubhamsingh.splashy.core.utils.SettingsUtils 20 | import dev.ishubhamsingh.splashy.features.settings.ui.SettingsEvent 21 | import dev.ishubhamsingh.splashy.features.settings.ui.SettingsState 22 | import dev.ishubhamsingh.splashy.isMaterialYouEnabledState 23 | import dev.ishubhamsingh.splashy.selectedThemeState 24 | import kotlinx.coroutines.flow.MutableStateFlow 25 | import kotlinx.coroutines.flow.asStateFlow 26 | import kotlinx.coroutines.flow.update 27 | 28 | /** Created by Shubham Singh on 24/11/23. */ 29 | class SettingsScreenModel(val settingsUtils: SettingsUtils) : ScreenModel { 30 | 31 | private val _state = MutableStateFlow(SettingsState()) 32 | val state = _state.asStateFlow() 33 | 34 | init { 35 | val currentTheme = settingsUtils.fetchInt(SettingsUtils.THEME, Theme.SYSTEM.value) 36 | val isMaterialYouEnabled = 37 | settingsUtils.fetchBoolean(SettingsUtils.IS_MATERIAL_YOU_ENABLED, true) 38 | 39 | _state.update { 40 | it.copy(selectedTheme = currentTheme, isMaterialYouEnabled = isMaterialYouEnabled) 41 | } 42 | } 43 | 44 | fun onEvent(event: SettingsEvent) { 45 | when (event) { 46 | is SettingsEvent.OnThemeChange -> { 47 | settingsUtils.storeInt(SettingsUtils.THEME, event.selectedTheme) 48 | _state.update { 49 | it.copy( 50 | selectedTheme = event.selectedTheme, 51 | ) 52 | } 53 | selectedThemeState.value = event.selectedTheme 54 | } 55 | is SettingsEvent.OnMaterialYouToggle -> { 56 | settingsUtils.storeBoolean( 57 | SettingsUtils.IS_MATERIAL_YOU_ENABLED, 58 | event.isMaterialYouEnabled 59 | ) 60 | _state.update { 61 | it.copy( 62 | isMaterialYouEnabled = event.isMaterialYouEnabled, 63 | ) 64 | } 65 | isMaterialYouEnabledState.value = event.isMaterialYouEnabled 66 | } 67 | SettingsEvent.ShowThemeSelectionDialog -> { 68 | _state.update { 69 | it.copy( 70 | showThemeSelectionDialog = true, 71 | ) 72 | } 73 | } 74 | SettingsEvent.HideThemeSelectionDialog -> { 75 | _state.update { 76 | it.copy( 77 | showThemeSelectionDialog = false, 78 | ) 79 | } 80 | } 81 | } 82 | } 83 | } 84 | 85 | enum class Theme(val value: Int) { 86 | LIGHT(0), 87 | DARK(1), 88 | SYSTEM(2) 89 | } 90 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/settings/ui/SettingsEvent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.settings.ui 17 | 18 | import dev.ishubhamsingh.splashy.core.domain.ScreenEvent 19 | 20 | /** Created by Shubham Singh on 24/11/23. */ 21 | sealed class SettingsEvent : ScreenEvent { 22 | data class OnThemeChange(val selectedTheme: Int) : SettingsEvent() 23 | 24 | data class OnMaterialYouToggle(val isMaterialYouEnabled: Boolean) : SettingsEvent() 25 | 26 | data object ShowThemeSelectionDialog : SettingsEvent() 27 | 28 | data object HideThemeSelectionDialog : SettingsEvent() 29 | } 30 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/features/settings/ui/SettingsState.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.features.settings.ui 17 | 18 | import dev.ishubhamsingh.splashy.features.settings.Theme 19 | 20 | /** Created by Shubham Singh on 24/11/23. */ 21 | data class SettingsState( 22 | val selectedTheme: Int = Theme.SYSTEM.value, 23 | val isMaterialYouEnabled: Boolean = true, 24 | val showThemeSelectionDialog: Boolean = false 25 | ) 26 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/CollectionItem.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import kotlinx.serialization.SerialName 19 | import kotlinx.serialization.Serializable 20 | 21 | @Serializable 22 | data class CollectionItem( 23 | @SerialName("cover_photo") val coverPhoto: CoverPhoto? = null, 24 | @SerialName("description") val description: String? = null, 25 | @SerialName("id") val id: String? = null, 26 | @SerialName("last_collected_at") val lastCollectedAt: String? = null, 27 | @SerialName("links") val links: Links? = null, 28 | @SerialName("private") val isPrivate: Boolean? = null, 29 | @SerialName("preview_photos") val previewPhotos: ArrayList? = null, 30 | @SerialName("published_at") val publishedAt: String? = null, 31 | @SerialName("share_key") val shareKey: String? = null, 32 | @SerialName("title") val title: String? = null, 33 | @SerialName("total_photos") val totalPhotos: Int? = null, 34 | @SerialName("updated_at") val updatedAt: String? = null, 35 | @SerialName("user") val user: User? = null 36 | ) { 37 | @Serializable 38 | data class CoverPhoto( 39 | @SerialName("blur_hash") val blurHash: String? = null, 40 | @SerialName("color") val color: String? = null, 41 | @SerialName("description") val description: String? = null, 42 | @SerialName("height") val height: Int? = null, 43 | @SerialName("id") val id: String? = null, 44 | @SerialName("liked_by_user") val likedByUser: Boolean? = null, 45 | @SerialName("likes") val likes: Int? = null, 46 | @SerialName("links") val links: Links? = null, 47 | @SerialName("urls") val urls: Urls? = null, 48 | @SerialName("user") val user: User? = null, 49 | @SerialName("width") val width: Int? = null 50 | ) { 51 | @Serializable 52 | data class Links( 53 | @SerialName("download") val download: String? = null, 54 | @SerialName("html") val html: String? = null, 55 | @SerialName("self") val self: String? = null 56 | ) 57 | 58 | @Serializable 59 | data class Urls( 60 | @SerialName("full") val full: String? = null, 61 | @SerialName("raw") val raw: String? = null, 62 | @SerialName("regular") val regular: String? = null, 63 | @SerialName("small") val small: String? = null, 64 | @SerialName("thumb") val thumb: String? = null 65 | ) 66 | 67 | @Serializable 68 | data class User( 69 | @SerialName("bio") val bio: String? = null, 70 | @SerialName("id") val id: String? = null, 71 | @SerialName("links") val links: Links? = null, 72 | @SerialName("location") val location: String? = null, 73 | @SerialName("name") val name: String? = null, 74 | @SerialName("portfolio_url") val portfolioUrl: String? = null, 75 | @SerialName("profile_image") val profileImage: ProfileImage? = null, 76 | @SerialName("total_collections") val totalCollections: Int? = null, 77 | @SerialName("total_likes") val totalLikes: Int? = null, 78 | @SerialName("total_photos") val totalPhotos: Int? = null, 79 | @SerialName("username") val username: String? = null 80 | ) { 81 | @Serializable 82 | data class Links( 83 | @SerialName("html") val html: String? = null, 84 | @SerialName("likes") val likes: String? = null, 85 | @SerialName("photos") val photos: String? = null, 86 | @SerialName("portfolio") val portfolio: String? = null, 87 | @SerialName("self") val self: String? = null 88 | ) 89 | 90 | @Serializable 91 | data class ProfileImage( 92 | @SerialName("large") val large: String? = null, 93 | @SerialName("medium") val medium: String? = null, 94 | @SerialName("small") val small: String? = null 95 | ) 96 | } 97 | } 98 | 99 | @Serializable 100 | data class Links( 101 | @SerialName("html") val html: String? = null, 102 | @SerialName("photos") val photos: String? = null, 103 | @SerialName("related") val related: String? = null, 104 | @SerialName("self") val self: String? = null 105 | ) 106 | 107 | @Serializable 108 | data class User( 109 | @SerialName("bio") val bio: String? = null, 110 | @SerialName("id") val id: String? = null, 111 | @SerialName("links") val links: Links? = null, 112 | @SerialName("location") val location: String? = null, 113 | @SerialName("name") val name: String? = null, 114 | @SerialName("portfolio_url") val portfolioUrl: String? = null, 115 | @SerialName("profile_image") val profileImage: ProfileImage? = null, 116 | @SerialName("total_collections") val totalCollections: Int? = null, 117 | @SerialName("total_likes") val totalLikes: Int? = null, 118 | @SerialName("total_photos") val totalPhotos: Int? = null, 119 | @SerialName("updated_at") val updatedAt: String? = null, 120 | @SerialName("username") val username: String? = null 121 | ) { 122 | @Serializable 123 | data class Links( 124 | @SerialName("html") val html: String? = null, 125 | @SerialName("likes") val likes: String? = null, 126 | @SerialName("photos") val photos: String? = null, 127 | @SerialName("portfolio") val portfolio: String? = null, 128 | @SerialName("self") val self: String? = null 129 | ) 130 | 131 | @Serializable 132 | data class ProfileImage( 133 | @SerialName("large") val large: String? = null, 134 | @SerialName("medium") val medium: String? = null, 135 | @SerialName("small") val small: String? = null 136 | ) 137 | } 138 | 139 | @Serializable 140 | data class PreviewPhotos( 141 | @SerialName("blur_hash") val blurHash: String? = null, 142 | @SerialName("created_at") val createdAt: String? = null, 143 | @SerialName("id") val id: String? = null, 144 | @SerialName("slug") val slug: String? = null, 145 | @SerialName("updated_at") val updatedAt: String? = null, 146 | @SerialName("urls") val urls: Urls? = null 147 | ) { 148 | @Serializable 149 | data class Urls( 150 | @SerialName("full") val full: String? = null, 151 | @SerialName("raw") val raw: String? = null, 152 | @SerialName("regular") val regular: String? = null, 153 | @SerialName("small") val small: String? = null, 154 | @SerialName("small_s3") val smallS3: String? = null, 155 | @SerialName("thumb") val thumb: String? = null 156 | ) 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/DownloadUrl.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import kotlinx.serialization.Serializable 19 | 20 | /** Created by Shubham Singh on 20/08/23. */ 21 | @Serializable data class DownloadUrl(val url: String) 22 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/Favourite.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import kotlinx.serialization.Serializable 19 | 20 | /** Created by Shubham Singh on 12/08/23. */ 21 | @Serializable 22 | data class Favourite( 23 | val id: String, 24 | val color: String?, 25 | val altDescription: String?, 26 | val description: String?, 27 | val topicSubmissions: TopicSubmissions?, 28 | val url: String?, 29 | ) 30 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/Links.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import cafe.adriel.voyager.core.lifecycle.JavaSerializable 19 | import kotlinx.serialization.SerialName 20 | import kotlinx.serialization.Serializable 21 | import kotlinx.serialization.encodeToString 22 | import kotlinx.serialization.json.Json 23 | 24 | @Serializable 25 | data class Links( 26 | @SerialName("download") val download: String = "", 27 | @SerialName("download_location") val downloadLocation: String = "", 28 | @SerialName("html") val html: String = "", 29 | @SerialName("self") val self: String = "" 30 | ) : JavaSerializable { 31 | override fun toString(): String { 32 | return Json.encodeToString(this) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/LinksX.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import cafe.adriel.voyager.core.lifecycle.JavaSerializable 19 | import kotlinx.serialization.SerialName 20 | import kotlinx.serialization.Serializable 21 | 22 | @Serializable 23 | data class LinksX( 24 | @SerialName("followers") val followers: String = "", 25 | @SerialName("following") val following: String = "", 26 | @SerialName("html") val html: String = "", 27 | @SerialName("likes") val likes: String = "", 28 | @SerialName("photos") val photos: String = "", 29 | @SerialName("portfolio") val portfolio: String = "", 30 | @SerialName("self") val self: String = "" 31 | ) : JavaSerializable 32 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/Photo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import cafe.adriel.voyager.core.lifecycle.JavaSerializable 19 | import kotlinx.serialization.SerialName 20 | import kotlinx.serialization.Serializable 21 | 22 | @Serializable 23 | data class Photo( 24 | @SerialName("alt_description") val altDescription: String? = "", 25 | @SerialName("color") val color: String = "", 26 | @SerialName("created_at") val createdAt: String? = "", 27 | @SerialName("description") val description: String? = "", 28 | @SerialName("height") val height: Int = 0, 29 | @SerialName("id") val id: String = "", 30 | @SerialName("likes") val likes: Int = 0, 31 | @SerialName("links") val links: Links? = Links(), 32 | @SerialName("promoted_at") val promotedAt: String? = "", 33 | @SerialName("topic_submissions") val topicSubmissions: TopicSubmissions? = TopicSubmissions(), 34 | @SerialName("updated_at") val updatedAt: String? = "", 35 | @SerialName("urls") val urls: Urls? = Urls(), 36 | @SerialName("user") val user: User? = User(), 37 | @SerialName("width") val width: Int = 0 38 | ) : JavaSerializable 39 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/PhotoSearchCollection.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import kotlinx.serialization.SerialName 19 | import kotlinx.serialization.Serializable 20 | 21 | @Serializable 22 | data class PhotoSearchCollection( 23 | @SerialName("results") val results: ArrayList = arrayListOf(), 24 | @SerialName("total") val total: Int = 0, 25 | @SerialName("total_pages") val totalPages: Int = 0 26 | ) 27 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/ProfileImage.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import cafe.adriel.voyager.core.lifecycle.JavaSerializable 19 | import kotlinx.serialization.SerialName 20 | import kotlinx.serialization.Serializable 21 | 22 | @Serializable 23 | data class ProfileImage( 24 | @SerialName("large") val large: String = "", 25 | @SerialName("medium") val medium: String = "", 26 | @SerialName("small") val small: String = "" 27 | ) : JavaSerializable 28 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/Social.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import cafe.adriel.voyager.core.lifecycle.JavaSerializable 19 | import kotlinx.serialization.SerialName 20 | import kotlinx.serialization.Serializable 21 | 22 | @Serializable 23 | data class Social( 24 | @SerialName("instagram_username") val instagramUsername: String? = "", 25 | @SerialName("paypal_email") val paypalEmail: String? = null, 26 | @SerialName("portfolio_url") val portfolioUrl: String? = null, 27 | @SerialName("twitter_username") val twitterUsername: String? = null 28 | ) : JavaSerializable 29 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/Sponsor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import kotlinx.serialization.SerialName 19 | import kotlinx.serialization.Serializable 20 | 21 | @Serializable 22 | data class Sponsor( 23 | @SerialName("accepted_tos") val acceptedTos: Boolean? = false, 24 | @SerialName("bio") val bio: String? = "", 25 | @SerialName("first_name") val firstName: String? = "", 26 | @SerialName("for_hire") val forHire: Boolean? = false, 27 | @SerialName("id") val id: String? = "", 28 | @SerialName("instagram_username") val instagramUsername: String? = "", 29 | @SerialName("last_name") val lastName: String? = null, 30 | @SerialName("links") val links: LinksX? = LinksX(), 31 | @SerialName("location") val location: String? = "", 32 | @SerialName("name") val name: String? = "", 33 | @SerialName("portfolio_url") val portfolioUrl: String? = "", 34 | @SerialName("profile_image") val profileImage: ProfileImage? = ProfileImage(), 35 | @SerialName("social") val social: Social? = Social(), 36 | @SerialName("total_collections") val totalCollections: Int? = 0, 37 | @SerialName("total_likes") val totalLikes: Int? = 0, 38 | @SerialName("total_photos") val totalPhotos: Int? = 0, 39 | @SerialName("twitter_username") val twitterUsername: String? = "", 40 | @SerialName("updated_at") val updatedAt: String? = "", 41 | @SerialName("username") val username: String? = "" 42 | ) 43 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/Sponsorship.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import kotlinx.serialization.SerialName 19 | import kotlinx.serialization.Serializable 20 | 21 | @Serializable 22 | data class Sponsorship( 23 | @SerialName("impression_urls") val impressionUrls: List = listOf(), 24 | @SerialName("sponsor") val sponsor: Sponsor = Sponsor(), 25 | @SerialName("tagline") val tagline: String = "", 26 | @SerialName("tagline_url") val taglineUrl: String = "" 27 | ) 28 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/TopicFilter.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import kotlinx.serialization.Serializable 19 | 20 | /** Created by Shubham Singh on 13/08/23. */ 21 | @Serializable data class TopicFilter(val topic: String, val isSelected: Boolean = false) 22 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/TopicSubmissionStatus.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import cafe.adriel.voyager.core.lifecycle.JavaSerializable 19 | import kotlinx.serialization.SerialName 20 | import kotlinx.serialization.Serializable 21 | 22 | @Serializable 23 | data class TopicSubmissionStatus( 24 | @SerialName("approved_on") val approvedOn: String = "", 25 | @SerialName("status") val status: String = "" 26 | ) : JavaSerializable 27 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/TopicSubmissions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import cafe.adriel.voyager.core.lifecycle.JavaSerializable 19 | import kotlinx.serialization.SerialName 20 | import kotlinx.serialization.Serializable 21 | import kotlinx.serialization.encodeToString 22 | import kotlinx.serialization.json.Json 23 | 24 | @Serializable 25 | data class TopicSubmissions( 26 | @SerialName("architecture-interior") val architectureInterior: TopicSubmissionStatus? = null, 27 | @SerialName("experimental") val experimental: TopicSubmissionStatus? = null, 28 | @SerialName("fashion-beauty") val fashionBeauty: TopicSubmissionStatus? = null, 29 | @SerialName("street-photography") val streetPhotography: TopicSubmissionStatus? = null, 30 | @SerialName("wallpapers") val wallpapers: TopicSubmissionStatus? = null, 31 | @SerialName("travel") val travel: TopicSubmissionStatus? = null, 32 | @SerialName("arts-culture") val artsCulture: TopicSubmissionStatus? = null, 33 | @SerialName("athletics") val athletics: TopicSubmissionStatus? = null, 34 | @SerialName("color-of-water") val colorOfWater: TopicSubmissionStatus? = null, 35 | @SerialName("health") val health: TopicSubmissionStatus? = null, 36 | @SerialName("nature") val nature: TopicSubmissionStatus? = null, 37 | @SerialName("people") val people: TopicSubmissionStatus? = null, 38 | @SerialName("spirituality") val spirituality: TopicSubmissionStatus? = null, 39 | @SerialName("textures-patterns") val texturesPatterns: TopicSubmissionStatus? = null 40 | ) : JavaSerializable { 41 | private val topicSubmissionMap = 42 | hashMapOf( 43 | "Wallpapers" to wallpapers, 44 | "Experimental" to experimental, 45 | "Travel" to travel, 46 | "Fashion Beauty" to fashionBeauty, 47 | "Street Photography" to streetPhotography, 48 | "Architecture Interior" to architectureInterior, 49 | "Travel" to travel, 50 | "Arts Culture" to artsCulture, 51 | "Athletics" to athletics, 52 | "Color Of Water" to colorOfWater, 53 | "Health" to health, 54 | "Nature" to nature, 55 | "People" to people, 56 | "Spirituality" to spirituality, 57 | "Textures Patterns" to texturesPatterns 58 | ) 59 | 60 | fun getApprovedTopics(): ArrayList { 61 | val approvedList = arrayListOf() 62 | topicSubmissionMap.entries.forEach { item -> 63 | item.let { 64 | if (it.value != null && it.value?.status == "approved") approvedList.add(item.key) 65 | } 66 | } 67 | return approvedList 68 | } 69 | 70 | override fun toString(): String { 71 | return Json.encodeToString(this) 72 | } 73 | 74 | fun containsAnyTopic(topicFilters: ArrayList): Boolean { 75 | if (topicFilters.any { it.isSelected }.not()) return true 76 | 77 | val selectedFilters: List = 78 | topicFilters.mapNotNull { if (it.isSelected) it.topic else null } 79 | return selectedFilters.any { getApprovedTopics().contains(it) } 80 | } 81 | 82 | companion object { 83 | val TOPICS = ArrayList(TopicSubmissions().topicSubmissionMap.keys.map { TopicFilter(it) }) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/Urls.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import cafe.adriel.voyager.core.lifecycle.JavaSerializable 19 | import kotlinx.serialization.SerialName 20 | import kotlinx.serialization.Serializable 21 | import kotlinx.serialization.encodeToString 22 | import kotlinx.serialization.json.Json 23 | 24 | @Serializable 25 | data class Urls( 26 | @SerialName("full") val full: String = "", 27 | @SerialName("raw") val raw: String = "", 28 | @SerialName("regular") val regular: String = "", 29 | @SerialName("small") val small: String = "", 30 | @SerialName("small_s3") val smallS3: String = "", 31 | @SerialName("thumb") val thumb: String = "" 32 | ) : JavaSerializable { 33 | override fun toString(): String { 34 | return Json.encodeToString(this) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/models/User.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.models 17 | 18 | import cafe.adriel.voyager.core.lifecycle.JavaSerializable 19 | import kotlinx.serialization.SerialName 20 | import kotlinx.serialization.Serializable 21 | import kotlinx.serialization.encodeToString 22 | import kotlinx.serialization.json.Json 23 | 24 | @Serializable 25 | data class User( 26 | @SerialName("accepted_tos") val acceptedTos: Boolean? = false, 27 | @SerialName("bio") val bio: String? = "", 28 | @SerialName("first_name") val firstName: String? = "", 29 | @SerialName("for_hire") val forHire: Boolean? = false, 30 | @SerialName("id") val id: String? = "", 31 | @SerialName("instagram_username") val instagramUsername: String? = "", 32 | @SerialName("last_name") val lastName: String? = "", 33 | @SerialName("links") val links: LinksX? = LinksX(), 34 | @SerialName("location") val location: String? = "", 35 | @SerialName("name") val name: String? = "", 36 | @SerialName("portfolio_url") val portfolioUrl: String? = "", 37 | @SerialName("profile_image") val profileImage: ProfileImage? = ProfileImage(), 38 | @SerialName("social") val social: Social? = Social(), 39 | @SerialName("total_collections") val totalCollections: Int? = 0, 40 | @SerialName("total_likes") val totalLikes: Int? = 0, 41 | @SerialName("total_photos") val totalPhotos: Int? = 0, 42 | @SerialName("twitter_username") val twitterUsername: String? = "", 43 | @SerialName("updated_at") val updatedAt: String? = "", 44 | @SerialName("username") val username: String? = "" 45 | ) : JavaSerializable { 46 | override fun toString(): String { 47 | return Json.encodeToString(this) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.ui.theme 17 | 18 | import androidx.compose.ui.graphics.Color 19 | 20 | val md_theme_light_primary = Color(0xFF006C45) 21 | val md_theme_light_onPrimary = Color(0xFFFFFFFF) 22 | val md_theme_light_primaryContainer = Color(0xFF8FF7BF) 23 | val md_theme_light_onPrimaryContainer = Color(0xFF002112) 24 | val md_theme_light_secondary = Color(0xFF4E6355) 25 | val md_theme_light_onSecondary = Color(0xFFFFFFFF) 26 | val md_theme_light_secondaryContainer = Color(0xFFD0E8D7) 27 | val md_theme_light_onSecondaryContainer = Color(0xFF0B1F15) 28 | val md_theme_light_tertiary = Color(0xFF3C6472) 29 | val md_theme_light_onTertiary = Color(0xFFFFFFFF) 30 | val md_theme_light_tertiaryContainer = Color(0xFFBFE9F9) 31 | val md_theme_light_onTertiaryContainer = Color(0xFF001F28) 32 | val md_theme_light_error = Color(0xFFBA1A1A) 33 | val md_theme_light_errorContainer = Color(0xFFFFDAD6) 34 | val md_theme_light_onError = Color(0xFFFFFFFF) 35 | val md_theme_light_onErrorContainer = Color(0xFF410002) 36 | val md_theme_light_background = Color(0xFFFBFDF8) 37 | val md_theme_light_onBackground = Color(0xFF191C1A) 38 | val md_theme_light_surface = Color(0xFFFBFDF8) 39 | val md_theme_light_onSurface = Color(0xFF191C1A) 40 | val md_theme_light_surfaceVariant = Color(0xFFDCE5DC) 41 | val md_theme_light_onSurfaceVariant = Color(0xFF404943) 42 | val md_theme_light_outline = Color(0xFF707972) 43 | val md_theme_light_inverseOnSurface = Color(0xFFEFF1ED) 44 | val md_theme_light_inverseSurface = Color(0xFF2E312E) 45 | val md_theme_light_inversePrimary = Color(0xFF73DAA4) 46 | val md_theme_light_shadow = Color(0xFF000000) 47 | val md_theme_light_surfaceTint = Color(0xFF006C45) 48 | val md_theme_light_outlineVariant = Color(0xFFC0C9C1) 49 | val md_theme_light_scrim = Color(0xFF000000) 50 | 51 | val md_theme_dark_primary = Color(0xFF73DAA4) 52 | val md_theme_dark_onPrimary = Color(0xFF003822) 53 | val md_theme_dark_primaryContainer = Color(0xFF005233) 54 | val md_theme_dark_onPrimaryContainer = Color(0xFF8FF7BF) 55 | val md_theme_dark_secondary = Color(0xFFB4CCBB) 56 | val md_theme_dark_onSecondary = Color(0xFF203529) 57 | val md_theme_dark_secondaryContainer = Color(0xFF364B3F) 58 | val md_theme_dark_onSecondaryContainer = Color(0xFFD0E8D7) 59 | val md_theme_dark_tertiary = Color(0xFFA4CDDD) 60 | val md_theme_dark_onTertiary = Color(0xFF053542) 61 | val md_theme_dark_tertiaryContainer = Color(0xFF234C59) 62 | val md_theme_dark_onTertiaryContainer = Color(0xFFBFE9F9) 63 | val md_theme_dark_error = Color(0xFFFFB4AB) 64 | val md_theme_dark_errorContainer = Color(0xFF93000A) 65 | val md_theme_dark_onError = Color(0xFF690005) 66 | val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) 67 | val md_theme_dark_background = Color(0xFF191C1A) 68 | val md_theme_dark_onBackground = Color(0xFFE1E3DF) 69 | val md_theme_dark_surface = Color(0xFF191C1A) 70 | val md_theme_dark_onSurface = Color(0xFFE1E3DF) 71 | val md_theme_dark_surfaceVariant = Color(0xFF404943) 72 | val md_theme_dark_onSurfaceVariant = Color(0xFFC0C9C1) 73 | val md_theme_dark_outline = Color(0xFF8A938B) 74 | val md_theme_dark_inverseOnSurface = Color(0xFF191C1A) 75 | val md_theme_dark_inverseSurface = Color(0xFFE1E3DF) 76 | val md_theme_dark_inversePrimary = Color(0xFF006C45) 77 | val md_theme_dark_shadow = Color(0xFF000000) 78 | val md_theme_dark_surfaceTint = Color(0xFF73DAA4) 79 | val md_theme_dark_outlineVariant = Color(0xFF404943) 80 | val md_theme_dark_scrim = Color(0xFF000000) 81 | 82 | val seed = Color(0xFF246A49) 83 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.ui.theme 17 | 18 | import androidx.compose.foundation.shape.RoundedCornerShape 19 | import androidx.compose.material3.Shapes 20 | import androidx.compose.material3.darkColorScheme 21 | import androidx.compose.material3.lightColorScheme 22 | import androidx.compose.ui.unit.dp 23 | 24 | val LightColors = 25 | lightColorScheme( 26 | primary = md_theme_light_primary, 27 | onPrimary = md_theme_light_onPrimary, 28 | primaryContainer = md_theme_light_primaryContainer, 29 | onPrimaryContainer = md_theme_light_onPrimaryContainer, 30 | secondary = md_theme_light_secondary, 31 | onSecondary = md_theme_light_onSecondary, 32 | secondaryContainer = md_theme_light_secondaryContainer, 33 | onSecondaryContainer = md_theme_light_onSecondaryContainer, 34 | tertiary = md_theme_light_tertiary, 35 | onTertiary = md_theme_light_onTertiary, 36 | tertiaryContainer = md_theme_light_tertiaryContainer, 37 | onTertiaryContainer = md_theme_light_onTertiaryContainer, 38 | error = md_theme_light_error, 39 | errorContainer = md_theme_light_errorContainer, 40 | onError = md_theme_light_onError, 41 | onErrorContainer = md_theme_light_onErrorContainer, 42 | background = md_theme_light_background, 43 | onBackground = md_theme_light_onBackground, 44 | surface = md_theme_light_surface, 45 | onSurface = md_theme_light_onSurface, 46 | surfaceVariant = md_theme_light_surfaceVariant, 47 | onSurfaceVariant = md_theme_light_onSurfaceVariant, 48 | outline = md_theme_light_outline, 49 | inverseOnSurface = md_theme_light_inverseOnSurface, 50 | inverseSurface = md_theme_light_inverseSurface, 51 | inversePrimary = md_theme_light_inversePrimary, 52 | surfaceTint = md_theme_light_surfaceTint, 53 | outlineVariant = md_theme_light_outlineVariant, 54 | scrim = md_theme_light_scrim, 55 | ) 56 | 57 | val DarkColors = 58 | darkColorScheme( 59 | primary = md_theme_dark_primary, 60 | onPrimary = md_theme_dark_onPrimary, 61 | primaryContainer = md_theme_dark_primaryContainer, 62 | onPrimaryContainer = md_theme_dark_onPrimaryContainer, 63 | secondary = md_theme_dark_secondary, 64 | onSecondary = md_theme_dark_onSecondary, 65 | secondaryContainer = md_theme_dark_secondaryContainer, 66 | onSecondaryContainer = md_theme_dark_onSecondaryContainer, 67 | tertiary = md_theme_dark_tertiary, 68 | onTertiary = md_theme_dark_onTertiary, 69 | tertiaryContainer = md_theme_dark_tertiaryContainer, 70 | onTertiaryContainer = md_theme_dark_onTertiaryContainer, 71 | error = md_theme_dark_error, 72 | errorContainer = md_theme_dark_errorContainer, 73 | onError = md_theme_dark_onError, 74 | onErrorContainer = md_theme_dark_onErrorContainer, 75 | background = md_theme_dark_background, 76 | onBackground = md_theme_dark_onBackground, 77 | surface = md_theme_dark_surface, 78 | onSurface = md_theme_dark_onSurface, 79 | surfaceVariant = md_theme_dark_surfaceVariant, 80 | onSurfaceVariant = md_theme_dark_onSurfaceVariant, 81 | outline = md_theme_dark_outline, 82 | inverseOnSurface = md_theme_dark_inverseOnSurface, 83 | inverseSurface = md_theme_dark_inverseSurface, 84 | inversePrimary = md_theme_dark_inversePrimary, 85 | surfaceTint = md_theme_dark_surfaceTint, 86 | outlineVariant = md_theme_dark_outlineVariant, 87 | scrim = md_theme_dark_scrim, 88 | ) 89 | 90 | val Shapes = 91 | Shapes( 92 | extraSmall = RoundedCornerShape(2.dp), 93 | small = RoundedCornerShape(4.dp), 94 | medium = RoundedCornerShape(8.dp), 95 | large = RoundedCornerShape(16.dp), 96 | extraLarge = RoundedCornerShape(32.dp) 97 | ) 98 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/kotlin/dev/ishubhamsingh/splashy/ui/theme/Typography.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.ui.theme 17 | 18 | import androidx.compose.material3.Typography 19 | import androidx.compose.runtime.Composable 20 | import androidx.compose.ui.text.TextStyle 21 | import androidx.compose.ui.text.font.FontFamily 22 | import androidx.compose.ui.text.font.FontStyle 23 | import androidx.compose.ui.text.font.FontWeight 24 | import androidx.compose.ui.unit.sp 25 | import dev.ishubhamsingh.splashy.resources.Res 26 | import dev.ishubhamsingh.splashy.resources.lato_black 27 | import dev.ishubhamsingh.splashy.resources.lato_bold 28 | import dev.ishubhamsingh.splashy.resources.lato_light 29 | import dev.ishubhamsingh.splashy.resources.lato_regular 30 | import dev.ishubhamsingh.splashy.resources.lato_thin 31 | import dev.ishubhamsingh.splashy.resources.lobster_regular 32 | import org.jetbrains.compose.resources.Font 33 | 34 | @Composable 35 | fun getLatoRegular() = 36 | FontFamily( 37 | Font(resource = Res.font.lato_regular, weight = FontWeight.Normal, style = FontStyle.Normal) 38 | ) 39 | 40 | @Composable 41 | fun getLatoBold() = FontFamily(Font(Res.font.lato_bold, FontWeight.Bold, FontStyle.Normal)) 42 | 43 | @Composable 44 | fun getLatoBlack() = FontFamily(Font(Res.font.lato_black, FontWeight.Black, FontStyle.Normal)) 45 | 46 | @Composable 47 | fun getLatoThin() = FontFamily(Font(Res.font.lato_thin, FontWeight.Thin, FontStyle.Normal)) 48 | 49 | @Composable 50 | fun getLatoLight() = FontFamily(Font(Res.font.lato_light, FontWeight.Light, FontStyle.Normal)) 51 | 52 | @Composable 53 | fun getLobsterRegular() = 54 | FontFamily(Font(Res.font.lobster_regular, FontWeight.Normal, FontStyle.Normal)) 55 | 56 | @Composable 57 | fun getTypography(): Typography { 58 | 59 | val latoBlack = getLatoBlack() 60 | val latoBold = getLatoBold() 61 | val latoRegular = getLatoRegular() 62 | val latoThin = getLatoThin() 63 | val latoLight = getLatoLight() 64 | 65 | return Typography( 66 | displayLarge = 67 | TextStyle(fontFamily = latoBlack, fontWeight = FontWeight.Black, fontSize = 52.sp), 68 | displayMedium = 69 | TextStyle(fontFamily = latoBlack, fontWeight = FontWeight.Black, fontSize = 24.sp), 70 | displaySmall = 71 | TextStyle(fontFamily = latoBlack, fontWeight = FontWeight.Black, fontSize = 18.sp), 72 | headlineLarge = 73 | TextStyle(fontFamily = latoBlack, fontWeight = FontWeight.Black, fontSize = 24.sp), 74 | headlineMedium = 75 | TextStyle(fontFamily = latoBlack, fontWeight = FontWeight.Black, fontSize = 18.sp), 76 | headlineSmall = 77 | TextStyle(fontFamily = latoBlack, fontWeight = FontWeight.Black, fontSize = 16.sp), 78 | titleLarge = TextStyle(fontFamily = latoBold, fontWeight = FontWeight.Bold, fontSize = 24.sp), 79 | titleMedium = TextStyle(fontFamily = latoBold, fontWeight = FontWeight.Bold, fontSize = 18.sp), 80 | titleSmall = TextStyle(fontFamily = latoBold, fontWeight = FontWeight.Bold, fontSize = 16.sp), 81 | bodyLarge = 82 | TextStyle(fontFamily = latoRegular, fontWeight = FontWeight.Normal, fontSize = 24.sp), 83 | bodyMedium = 84 | TextStyle(fontFamily = latoRegular, fontWeight = FontWeight.Normal, fontSize = 18.sp), 85 | bodySmall = 86 | TextStyle(fontFamily = latoRegular, fontWeight = FontWeight.Normal, fontSize = 16.sp), 87 | labelLarge = TextStyle(fontFamily = latoLight, fontWeight = FontWeight.Light, fontSize = 18.sp), 88 | labelMedium = 89 | TextStyle(fontFamily = latoLight, fontWeight = FontWeight.Light, fontSize = 16.sp), 90 | labelSmall = TextStyle(fontFamily = latoLight, fontWeight = FontWeight.Light, fontSize = 14.sp) 91 | ) 92 | } 93 | -------------------------------------------------------------------------------- /composeApp/src/commonMain/sqldelight/dev/ishubhamsingh/splashy/db/Favourite.sq: -------------------------------------------------------------------------------- 1 | import dev.ishubhamsingh.splashy.models.TopicSubmissions; 2 | 3 | CREATE TABLE favouriteEntity ( 4 | id TEXT NOT NULL UNIQUE PRIMARY KEY, 5 | color TEXT, 6 | altDescription TEXT, 7 | description TEXT, 8 | topicSubmissions TEXT AS TopicSubmissions, 9 | url TEXT 10 | ); 11 | 12 | getFavourites: 13 | SELECT * 14 | FROM favouriteEntity; 15 | 16 | getFavouritesById: 17 | SELECT * 18 | FROM favouriteEntity 19 | WHERE id = :id; 20 | 21 | deleteFavourite: 22 | DELETE FROM favouriteEntity 23 | WHERE id = :id; 24 | 25 | deleteAllFavourites: 26 | DELETE FROM favouriteEntity; 27 | 28 | insertFavourite: 29 | INSERT OR REPLACE 30 | INTO favouriteEntity( 31 | id, 32 | color, 33 | altDescription, 34 | description, 35 | topicSubmissions, 36 | url 37 | ) VALUES ?; -------------------------------------------------------------------------------- /composeApp/src/commonMain/sqldelight/dev/ishubhamsingh/splashy/db/Photo.sq: -------------------------------------------------------------------------------- 1 | import dev.ishubhamsingh.splashy.models.Links; 2 | import dev.ishubhamsingh.splashy.models.TopicSubmissions; 3 | import dev.ishubhamsingh.splashy.models.Urls; 4 | import dev.ishubhamsingh.splashy.models.User; 5 | import kotlin.Int; 6 | 7 | CREATE TABLE photoEntity ( 8 | id TEXT NOT NULL UNIQUE PRIMARY KEY, 9 | color TEXT, 10 | altDescription TEXT, 11 | description TEXT, 12 | likes INTEGER AS Int, 13 | width INTEGER AS Int, 14 | height INTEGER AS Int, 15 | links TEXT AS Links, 16 | topicSubmissions TEXT AS TopicSubmissions, 17 | urls TEXT AS Urls, 18 | user TEXT AS User, 19 | promotedAt TEXT, 20 | updatedAt TEXT, 21 | createdAt TEXT 22 | ); 23 | 24 | getPhotos: 25 | SELECT * 26 | FROM photoEntity; 27 | 28 | getPhotosById: 29 | SELECT * 30 | FROM photoEntity 31 | WHERE id = :id; 32 | 33 | deletePhoto: 34 | DELETE FROM photoEntity 35 | WHERE id = :id; 36 | 37 | deleteAllPhotos: 38 | DELETE FROM photoEntity; 39 | 40 | insertPhoto: 41 | INSERT OR REPLACE 42 | INTO photoEntity( 43 | id, 44 | color, 45 | altDescription, 46 | description, 47 | likes, 48 | width, 49 | height, 50 | links, 51 | topicSubmissions, 52 | urls, 53 | user, 54 | promotedAt, 55 | updatedAt, 56 | createdAt 57 | ) VALUES ?; -------------------------------------------------------------------------------- /composeApp/src/iosMain/kotlin/dev/ishubhamsingh/splashy/App.ios.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy 17 | 18 | import androidx.compose.foundation.isSystemInDarkTheme 19 | import com.moriatsushi.insetsx.WindowInsetsUIViewController 20 | import platform.UIKit.UIViewController 21 | 22 | fun MainViewController(): UIViewController { 23 | return WindowInsetsUIViewController { 24 | App(darkTheme = isSystemInDarkTheme(), dynamicColor = false) 25 | } 26 | } 27 | 28 | fun OnBackGesture() { 29 | goBack.value = true 30 | } 31 | -------------------------------------------------------------------------------- /composeApp/src/iosMain/kotlin/dev/ishubhamsingh/splashy/core/di.components/PlatformModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.di.components 17 | 18 | import dev.ishubhamsingh.splashy.core.utils.DatabaseDriverFactory 19 | import dev.ishubhamsingh.splashy.core.utils.FileUtils 20 | import org.koin.dsl.module 21 | 22 | actual val platformModule = module { 23 | single { DatabaseDriverFactory() } 24 | factory { FileUtils() } 25 | } 26 | -------------------------------------------------------------------------------- /composeApp/src/iosMain/kotlin/dev/ishubhamsingh/splashy/core/presentation/SplashyTheme.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.presentation 17 | 18 | import androidx.compose.material3.MaterialTheme 19 | import androidx.compose.runtime.Composable 20 | import dev.ishubhamsingh.splashy.ui.theme.DarkColors 21 | import dev.ishubhamsingh.splashy.ui.theme.LightColors 22 | import dev.ishubhamsingh.splashy.ui.theme.Shapes 23 | import dev.ishubhamsingh.splashy.ui.theme.getTypography 24 | 25 | @Composable 26 | actual fun SplashyTheme( 27 | darkTheme: Boolean, 28 | dynamicColor: Boolean, 29 | content: @Composable () -> Unit 30 | ) { 31 | MaterialTheme( 32 | colorScheme = if (darkTheme) DarkColors else LightColors, 33 | typography = getTypography(), 34 | shapes = Shapes, 35 | content = content 36 | ) 37 | } 38 | -------------------------------------------------------------------------------- /composeApp/src/iosMain/kotlin/dev/ishubhamsingh/splashy/core/utils/CommonUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import androidx.compose.runtime.Composable 19 | import androidx.compose.ui.ExperimentalComposeUiApi 20 | import androidx.compose.ui.graphics.Color 21 | import androidx.compose.ui.platform.LocalWindowInfo 22 | import androidx.compose.ui.text.font.Font 23 | import io.ktor.client.HttpClient 24 | import io.ktor.client.engine.darwin.Darwin 25 | import kotlin.experimental.ExperimentalNativeApi 26 | import kotlin.native.Platform as NativePlatform 27 | import platform.Foundation.NSDateFormatter 28 | import platform.Foundation.NSISO8601DateFormatter 29 | import platform.Foundation.NSLocale 30 | import platform.Foundation.NSTimeZone 31 | import platform.Foundation.autoupdatingCurrentLocale 32 | import platform.Foundation.localTimeZone 33 | 34 | actual fun getHttpClient(): HttpClient { 35 | val httpClient = 36 | HttpClient(Darwin) { 37 | engine { 38 | configureRequest { 39 | setTimeoutInterval(5 * 60.0) 40 | setAllowsCellularAccess(true) 41 | } 42 | } 43 | } 44 | 45 | return httpClient 46 | } 47 | 48 | private val cache: MutableMap = mutableMapOf() 49 | 50 | actual fun getFormattedDateTime(timestamp: String, format: String): String { 51 | val date = NSISO8601DateFormatter().dateFromString(timestamp) ?: return "" 52 | 53 | val dateFormatter = NSDateFormatter() 54 | dateFormatter.timeZone = NSTimeZone.localTimeZone 55 | dateFormatter.locale = NSLocale.autoupdatingCurrentLocale 56 | dateFormatter.dateFormat = format 57 | return dateFormatter.stringFromDate(date) 58 | } 59 | 60 | actual fun getPlatform(): Platform = Platform.iOS 61 | 62 | @OptIn(ExperimentalNativeApi::class) actual fun isDebug(): Boolean = NativePlatform.isDebugBinary 63 | 64 | @OptIn(ExperimentalComposeUiApi::class) 65 | @Composable 66 | actual fun getScreenHeight(): Int { 67 | return LocalWindowInfo.current.containerSize.height 68 | } 69 | 70 | @Composable 71 | actual fun UpdateSystemBars( 72 | statusBarColor: Color, 73 | navigationBarColor: Color, 74 | isDarkTheme: Boolean 75 | ) {} 76 | -------------------------------------------------------------------------------- /composeApp/src/iosMain/kotlin/dev/ishubhamsingh/splashy/core/utils/DatabaseDriverFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import app.cash.sqldelight.db.SqlDriver 19 | import app.cash.sqldelight.driver.native.NativeSqliteDriver 20 | import app.cash.sqldelight.driver.native.wrapConnection 21 | import co.touchlab.sqliter.DatabaseConfiguration 22 | import dev.ishubhamsingh.splashy.db.SplashyDatabase 23 | 24 | /** Created by Shubham Singh on 11/08/23. */ 25 | actual class DatabaseDriverFactory { 26 | actual fun createDriver(): SqlDriver { 27 | return NativeSqliteDriver( 28 | DatabaseConfiguration( 29 | name = DB_NAME, 30 | version = SplashyDatabase.Schema.version.toInt(), 31 | create = { connection -> wrapConnection(connection) { SplashyDatabase.Schema.create(it) } }, 32 | upgrade = { connection, oldVersion, newVersion -> 33 | wrapConnection(connection) { 34 | SplashyDatabase.Schema.migrate(it, oldVersion.toLong(), newVersion.toLong()) 35 | } 36 | } 37 | ) 38 | ) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /composeApp/src/iosMain/kotlin/dev/ishubhamsingh/splashy/core/utils/FileUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package dev.ishubhamsingh.splashy.core.utils 17 | 18 | import com.eygraber.uri.Uri 19 | import dev.ishubhamsingh.splashy.features.details.WallpaperScreenType 20 | import dev.ishubhamsingh.splashy.resources.Res 21 | import dev.ishubhamsingh.splashy.resources.saved_failure_message 22 | import dev.ishubhamsingh.splashy.resources.saved_success_message 23 | import kotlin.coroutines.coroutineContext 24 | import kotlinx.cinterop.BetaInteropApi 25 | import kotlinx.cinterop.ExperimentalForeignApi 26 | import kotlinx.cinterop.allocArrayOf 27 | import kotlinx.cinterop.memScoped 28 | import kotlinx.coroutines.CoroutineScope 29 | import kotlinx.coroutines.Dispatchers 30 | import kotlinx.coroutines.IO 31 | import kotlinx.coroutines.launch 32 | import org.jetbrains.compose.resources.getString 33 | import platform.Foundation.NSData 34 | import platform.Foundation.create 35 | import platform.UIKit.UIImage 36 | import platform.UIKit.UIImageWriteToSavedPhotosAlbum 37 | 38 | /** Created by Shubham Singh on 19/08/23. */ 39 | actual class FileUtils { 40 | @OptIn(ExperimentalForeignApi::class, BetaInteropApi::class) 41 | actual suspend fun saveByteArrayToFile( 42 | fileName: String, 43 | data: ByteArray, 44 | shouldOpenFile: Boolean, 45 | updateMessage: (String) -> Unit 46 | ) { 47 | var result = "" 48 | CoroutineScope(coroutineContext).launch(Dispatchers.IO) { 49 | runCatching { 50 | val nsData: NSData = memScoped { 51 | NSData.create(bytes = allocArrayOf(data), length = data.size.toULong()) 52 | } 53 | val imageData = UIImage.imageWithData(data = nsData) 54 | if (imageData != null) { 55 | UIImageWriteToSavedPhotosAlbum(image = imageData, null, null, null) 56 | } else { 57 | throw NullPointerException() 58 | } 59 | } 60 | .onSuccess { 61 | result = getString(Res.string.saved_success_message) 62 | updateMessage.invoke(result) 63 | } 64 | .onFailure { 65 | result = getString(Res.string.saved_failure_message) 66 | updateMessage.invoke(result) 67 | it.printStackTrace() 68 | } 69 | } 70 | } 71 | 72 | actual suspend fun openFile(uri: Uri?, fileName: String) { 73 | // Do nothing 74 | } 75 | 76 | actual suspend fun applyWallpaper( 77 | data: ByteArray, 78 | wallpaperScreenType: WallpaperScreenType, 79 | updateMessage: (String) -> Unit 80 | ) { 81 | // Do nothing 82 | } 83 | 84 | actual suspend fun shouldAskStorageRuntimePermission(): Boolean { 85 | return true 86 | } 87 | 88 | actual suspend fun showMessage(message: String) { 89 | // Do nothing 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /gradle.bat: -------------------------------------------------------------------------------- 1 | 2 | @rem 3 | @rem Copyright 2015 the original author or authors. 4 | @rem 5 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 6 | @rem you may not use this file except in compliance with the License. 7 | @rem You may obtain a copy of the License at 8 | @rem 9 | @rem https://www.apache.org/licenses/LICENSE-2.0 10 | @rem 11 | @rem Unless required by applicable law or agreed to in writing, software 12 | @rem distributed under the License is distributed on an "AS IS" BASIS, 13 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | @rem See the License for the specific language governing permissions and 15 | @rem limitations under the License. 16 | @rem 17 | 18 | @if "%DEBUG%" == "" @echo off 19 | @rem ########################################################################## 20 | @rem 21 | @rem Gradle startup script for Windows 22 | @rem 23 | @rem ########################################################################## 24 | 25 | @rem Set local scope for the variables with windows NT shell 26 | if "%OS%"=="Windows_NT" setlocal 27 | 28 | set DIRNAME=%~dp0 29 | if "%DIRNAME%" == "" set DIRNAME=. 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if "%ERRORLEVEL%" == "0" goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | 2 | #Gradle 3 | org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M" 4 | 5 | #Kotlin 6 | kotlin.code.style=official 7 | kotlin.js.compiler=ir 8 | 9 | #MPP 10 | kotlin.mpp.enableCInteropCommonization=true 11 | kotlin.mpp.androidSourceSetLayoutVersion=2 12 | 13 | #Compose 14 | org.jetbrains.compose.experimental.uikit.enabled=true 15 | org.jetbrains.compose.experimental.jscanvas.enabled=true 16 | 17 | #Android 18 | android.useAndroidX=true 19 | android.nonTransitiveRClass=true 20 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | 3 | kotlin = "2.1.21" 4 | agp = "8.10.1" 5 | compose = "1.7.1" 6 | coil = "3.0.0-alpha08" 7 | androidx-appcompat = "1.7.1" 8 | androidx-activityCompose = "1.9.3" 9 | compose-uitooling = "1.7.8" 10 | material = "1.12.0" 11 | napier = "2.7.1" 12 | buildConfig = "5.6.5" 13 | kotlinx-coroutines = "1.10.2" 14 | insetsx = "0.1.0-alpha10" 15 | ktor = "2.3.13" 16 | composeIcons = "1.1.1" 17 | kotlinx-serialization = "1.8.1" 18 | multiplatformSettings = "1.3.0" 19 | koin = "4.0.4" 20 | koin-compose = "4.0.4" 21 | sqlDelight = "2.1.0" 22 | spotless = "7.0.4" 23 | ktfmt = "0.44" 24 | statelyCommon = "2.1.0" 25 | voyager = "1.0.1" 26 | moko-permissions = "0.18.1" 27 | kotlinx-datetime = "0.6.2" 28 | uri-kmp = "0.0.19" 29 | 30 | [libraries] 31 | 32 | androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" } 33 | androidx-activityCompose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" } 34 | compose-uitooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose-uitooling" } 35 | coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil"} 36 | coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil"} 37 | coil-ktor = { module = "io.coil-kt.coil3:coil-network-ktor", version.ref = "coil"} 38 | material = { module = "com.google.android.material:material", version.ref = "material" } 39 | napier = { module = "io.github.aakira:napier", version.ref = "napier" } 40 | kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } 41 | kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" } 42 | insetsx = { module = "com.moriatsushi.insetsx:insetsx", version.ref = "insetsx" } 43 | ktor-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } 44 | ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" } 45 | ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" } 46 | ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" } 47 | ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" } 48 | ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" } 49 | composeIcons-featherIcons = { module = "br.com.devsrsouza.compose.icons:feather", version.ref = "composeIcons" } 50 | composeIcons-evaIcons = { module = "br.com.devsrsouza.compose.icons:eva-icons", version.ref = "composeIcons" } 51 | composeIcons-octicons = { module = "br.com.devsrsouza.compose.icons:octicons", version.ref = "composeIcons" } 52 | kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" } 53 | multiplatformSettings = { module = "com.russhwolf:multiplatform-settings-no-arg", version.ref = "multiplatformSettings" } 54 | koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin" } 55 | koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin-compose" } 56 | koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin" } 57 | koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin" } 58 | sqlDelight-driver-sqlite = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqlDelight" } 59 | sqlDelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqlDelight" } 60 | sqlDelight-driver-native = { module = "app.cash.sqldelight:native-driver", version.ref = "sqlDelight" } 61 | sqlDelight-driver-sqljs = { module = "app.cash.sqldelight:sqljs-driver", version.ref = "sqlDelight" } 62 | sqlDelight-coroutines-extensions = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqlDelight" } 63 | sqlDelight-sqlite-dialect = { module = "app.cash.sqldelight:sqlite-3-24-dialect", version.ref = "sqlDelight" } 64 | stately-common = { module = "co.touchlab:stately-common", version.ref = "statelyCommon" } 65 | voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" } 66 | voyager-tabNavigator = { module = "cafe.adriel.voyager:voyager-tab-navigator", version.ref = "voyager" } 67 | voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" } 68 | voyager-koin = { module = "cafe.adriel.voyager:voyager-koin", version.ref = "voyager" } 69 | moko-permissions = { module = "dev.icerock.moko:permissions-compose", version.ref = "moko-permissions"} 70 | kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime"} 71 | uri-kmp = { module = "com.eygraber:uri-kmp", version.ref = "uri-kmp" } 72 | 73 | 74 | [plugins] 75 | 76 | multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } 77 | cocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" } 78 | compose = { id = "org.jetbrains.compose", version.ref = "compose" } 79 | compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } 80 | android-application = { id = "com.android.application", version.ref = "agp" } 81 | buildConfig = { id = "com.github.gmazzo.buildconfig", version.ref = "buildConfig" } 82 | kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } 83 | sqlDelight = { id = "app.cash.sqldelight", version.ref = "sqlDelight" } 84 | spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /iosApp/Configuration/Config.xcconfig: -------------------------------------------------------------------------------- 1 | TEAM_ID=A5CX8H4MPQ 2 | BUNDLE_ID=dev.ishubhamsingh.splashy.iosApp 3 | APP_NAME=Splashy 4 | -------------------------------------------------------------------------------- /iosApp/iosApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /iosApp/iosApp.xcodeproj/xcshareddata/xcschemes/iosApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 42 | 44 | 50 | 51 | 52 | 53 | 59 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "AppIcon@2x.png", 5 | "idiom": "iphone", 6 | "scale": "2x", 7 | "size": "60x60" 8 | }, 9 | { 10 | "filename": "AppIcon@3x.png", 11 | "idiom": "iphone", 12 | "scale": "3x", 13 | "size": "60x60" 14 | }, 15 | { 16 | "filename": "AppIcon~ipad.png", 17 | "idiom": "ipad", 18 | "scale": "1x", 19 | "size": "76x76" 20 | }, 21 | { 22 | "filename": "AppIcon@2x~ipad.png", 23 | "idiom": "ipad", 24 | "scale": "2x", 25 | "size": "76x76" 26 | }, 27 | { 28 | "filename": "AppIcon-83.5@2x~ipad.png", 29 | "idiom": "ipad", 30 | "scale": "2x", 31 | "size": "83.5x83.5" 32 | }, 33 | { 34 | "filename": "AppIcon-40@2x.png", 35 | "idiom": "iphone", 36 | "scale": "2x", 37 | "size": "40x40" 38 | }, 39 | { 40 | "filename": "AppIcon-40@3x.png", 41 | "idiom": "iphone", 42 | "scale": "3x", 43 | "size": "40x40" 44 | }, 45 | { 46 | "filename": "AppIcon-40~ipad.png", 47 | "idiom": "ipad", 48 | "scale": "1x", 49 | "size": "40x40" 50 | }, 51 | { 52 | "filename": "AppIcon-40@2x~ipad.png", 53 | "idiom": "ipad", 54 | "scale": "2x", 55 | "size": "40x40" 56 | }, 57 | { 58 | "filename": "AppIcon-20@2x.png", 59 | "idiom": "iphone", 60 | "scale": "2x", 61 | "size": "20x20" 62 | }, 63 | { 64 | "filename": "AppIcon-20@3x.png", 65 | "idiom": "iphone", 66 | "scale": "3x", 67 | "size": "20x20" 68 | }, 69 | { 70 | "filename": "AppIcon-20~ipad.png", 71 | "idiom": "ipad", 72 | "scale": "1x", 73 | "size": "20x20" 74 | }, 75 | { 76 | "filename": "AppIcon-20@2x~ipad.png", 77 | "idiom": "ipad", 78 | "scale": "2x", 79 | "size": "20x20" 80 | }, 81 | { 82 | "filename": "AppIcon-29.png", 83 | "idiom": "iphone", 84 | "scale": "1x", 85 | "size": "29x29" 86 | }, 87 | { 88 | "filename": "AppIcon-29@2x.png", 89 | "idiom": "iphone", 90 | "scale": "2x", 91 | "size": "29x29" 92 | }, 93 | { 94 | "filename": "AppIcon-29@3x.png", 95 | "idiom": "iphone", 96 | "scale": "3x", 97 | "size": "29x29" 98 | }, 99 | { 100 | "filename": "AppIcon-29~ipad.png", 101 | "idiom": "ipad", 102 | "scale": "1x", 103 | "size": "29x29" 104 | }, 105 | { 106 | "filename": "AppIcon-29@2x~ipad.png", 107 | "idiom": "ipad", 108 | "scale": "2x", 109 | "size": "29x29" 110 | }, 111 | { 112 | "filename": "AppIcon-60@2x~car.png", 113 | "idiom": "car", 114 | "scale": "2x", 115 | "size": "60x60" 116 | }, 117 | { 118 | "filename": "AppIcon-60@3x~car.png", 119 | "idiom": "car", 120 | "scale": "3x", 121 | "size": "60x60" 122 | }, 123 | { 124 | "filename": "AppIcon~ios-marketing.png", 125 | "idiom": "ios-marketing", 126 | "scale": "1x", 127 | "size": "1024x1024" 128 | } 129 | ], 130 | "info": { 131 | "author": "xcode", 132 | "version": 1 133 | } 134 | } -------------------------------------------------------------------------------- /iosApp/iosApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /iosApp/iosApp/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 | LSRequiresIPhoneOS 22 | 23 | CADisableMinimumFrameDurationOnPhone 24 | 25 | UIApplicationSceneManifest 26 | 27 | UIApplicationSupportsMultipleScenes 28 | 29 | 30 | UILaunchScreen 31 | 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | NSPhotoLibraryAddUsageDescription 50 | Our application needs permission to write photos to support download feature 51 | 52 | 53 | -------------------------------------------------------------------------------- /iosApp/iosApp/iosApp.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SwiftUI 3 | import ComposeApp 4 | import Foundation 5 | 6 | @main 7 | struct iosApp: App { 8 | 9 | init() { 10 | LoggingKt.initialiseLogging() 11 | DIHelperKt.doInitKoin() 12 | } 13 | var body: some Scene { 14 | WindowGroup { 15 | ContentView() 16 | } 17 | } 18 | } 19 | 20 | class ContainerViewController: UIViewController { 21 | private let onTouchDown: (CGPoint) -> Void 22 | 23 | init(child: UIViewController, onTouchDown: @escaping (CGPoint) -> Void) { 24 | self.onTouchDown = onTouchDown 25 | super.init(nibName: nil, bundle: nil) 26 | addChild(child) 27 | child.view.frame = view.frame 28 | view.addSubview(child.view) 29 | child.didMove(toParent: self) 30 | } 31 | 32 | required init?(coder: NSCoder) { 33 | fatalError("init(coder:) has not been implemented") 34 | } 35 | 36 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 37 | super.touchesBegan(touches, with: event) 38 | if let startPoint = touches.first?.location(in: nil) { 39 | onTouchDown(startPoint) 40 | } 41 | } 42 | } 43 | 44 | struct SwipeGestureViewController: UIViewControllerRepresentable { 45 | var onSwipe: () -> Void 46 | 47 | func makeUIViewController(context: Context) -> UIViewController { 48 | let viewController = App_iosKt.MainViewController() 49 | let containerController = ContainerViewController(child: viewController) { 50 | context.coordinator.startPoint = $0 51 | } 52 | 53 | let swipeGestureRecognizer = UISwipeGestureRecognizer( 54 | target: 55 | context.coordinator, action: #selector(Coordinator.handleSwipe) 56 | ) 57 | swipeGestureRecognizer.direction = .right 58 | swipeGestureRecognizer.numberOfTouchesRequired = 1 59 | containerController.view.addGestureRecognizer(swipeGestureRecognizer) 60 | return containerController 61 | } 62 | 63 | func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} 64 | 65 | func makeCoordinator() -> Coordinator { 66 | Coordinator(onSwipe: onSwipe) 67 | } 68 | 69 | class Coordinator: NSObject, UIGestureRecognizerDelegate { 70 | var onSwipe: () -> Void 71 | var startPoint: CGPoint? 72 | 73 | init(onSwipe: @escaping () -> Void) { 74 | self.onSwipe = onSwipe 75 | } 76 | 77 | @objc func handleSwipe(_ gesture: UISwipeGestureRecognizer) { 78 | if gesture.state == .ended, let startPoint = startPoint, startPoint.x < 50 { 79 | onSwipe() 80 | } 81 | } 82 | 83 | func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { 84 | true 85 | } 86 | } 87 | } 88 | 89 | struct ContentView: View { 90 | var body: some View { 91 | VStack { 92 | SwipeGestureViewController { 93 | onBackGesture() 94 | } 95 | }.ignoresSafeArea(.all, edges: .vertical) 96 | } 97 | } 98 | 99 | public func onBackGesture() { 100 | App_iosKt.OnBackGesture() 101 | } 102 | -------------------------------------------------------------------------------- /keystore/splashy.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishubhamsingh/Splashy/12daf0ea43928449473b68eee1bbed054edeaeb0/keystore/splashy.jks -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ], 6 | "automergeType": "branch", 7 | "packageRules": [ 8 | { 9 | "description": "Automerge non-major updates", 10 | "matchUpdateTypes": ["minor", "patch"], 11 | "automerge": true 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | rootProject.name = "Splashy" 17 | 18 | include(":composeApp") 19 | 20 | pluginManagement { 21 | repositories { 22 | google() 23 | gradlePluginPortal() 24 | mavenCentral() 25 | maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") 26 | } 27 | } 28 | 29 | dependencyResolutionManagement { 30 | @Suppress("UnstableApiUsage") 31 | repositories { 32 | google() 33 | mavenCentral() 34 | maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /spotless/copyright.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright $YEAR Shubham Singh 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ --------------------------------------------------------------------------------