├── wearOS
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values-round
│ │ │ └── strings.xml
│ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.webp
│ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.webp
│ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.webp
│ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.webp
│ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.webp
│ │ ├── values
│ │ │ ├── themes.xml
│ │ │ ├── strings.xml
│ │ │ └── dimens.xml
│ │ └── layout
│ │ │ └── activity_main.xml
│ │ ├── java
│ │ └── com
│ │ │ └── baseio
│ │ │ └── wearos
│ │ │ ├── ui
│ │ │ └── theme
│ │ │ │ ├── Color.kt
│ │ │ │ ├── Shape.kt
│ │ │ │ ├── Type.kt
│ │ │ │ └── Theme.kt
│ │ │ ├── PraxisApp.kt
│ │ │ ├── TrendingReposUI.kt
│ │ │ ├── TrendingReposVM.kt
│ │ │ └── TrendingReposListScreen.kt
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle.kts
├── compose-desktop
├── .gitignore
├── src
│ └── jvmMain
│ │ └── kotlin
│ │ ├── TrendingReposVM.kt
│ │ ├── Main.kt
│ │ └── TrendingReposListScreen.kt
└── build.gradle.kts
├── iosApp
├── .gitignore
├── iosApp
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ ├── iOSApp.swift
│ ├── githubtrending
│ │ ├── UiRepo.swift
│ │ ├── GithubTrendingUI.swift
│ │ └── GithubTrendingVM.swift
│ ├── AppDelegate.swift
│ └── Info.plist
├── Podfile
├── iosApp.xcworkspace
│ ├── xcuserdata
│ │ └── anmolverma.xcuserdatad
│ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ └── WorkspaceSettings.xcsettings
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
├── iosApp.xcodeproj
│ ├── xcuserdata
│ │ └── anmolverma.xcuserdatad
│ │ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── project.pbxproj
└── Podfile.lock
├── macOS
├── .gitignore
├── macOS
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ ├── ContentView.swift
│ ├── macOS.entitlements
│ ├── macOSApp.swift
│ └── githubtrending
│ │ ├── UiRepo.swift
│ │ ├── GithubTrendingUI.swift
│ │ └── GithubTrendingVM.swift
├── Podfile
├── macOS.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcuserdata
│ │ │ └── anmolverma.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── xcuserdata
│ │ └── anmolverma.xcuserdatad
│ │ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── project.pbxproj
├── macOS.xcworkspace
│ ├── xcuserdata
│ │ └── anmolverma.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── macOSUITests
│ ├── macOSUITestsLaunchTests.swift
│ └── macOSUITests.swift
└── macOSTests
│ └── macOSTests.swift
├── watchApp
├── .gitignore
├── watchApp WatchKit App
│ └── Assets.xcassets
│ │ ├── Contents.json
│ │ ├── AccentColor.colorset
│ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ └── Contents.json
├── watchApp WatchKit Extension
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── Complication.complicationset
│ │ │ ├── Graphic Bezel.imageset
│ │ │ └── Contents.json
│ │ │ ├── Graphic Corner.imageset
│ │ │ └── Contents.json
│ │ │ ├── Graphic Circular.imageset
│ │ │ └── Contents.json
│ │ │ ├── Graphic Large Rectangular.imageset
│ │ │ └── Contents.json
│ │ │ ├── Circular.imageset
│ │ │ └── Contents.json
│ │ │ ├── Modular.imageset
│ │ │ └── Contents.json
│ │ │ ├── Extra Large.imageset
│ │ │ └── Contents.json
│ │ │ ├── Utilitarian.imageset
│ │ │ └── Contents.json
│ │ │ ├── Graphic Extra Large.imageset
│ │ │ └── Contents.json
│ │ │ └── Contents.json
│ ├── Preview Content
│ │ └── Preview Assets.xcassets
│ │ │ └── Contents.json
│ ├── NotificationView.swift
│ ├── Info.plist
│ ├── githubtrending
│ │ ├── UiRepo.swift
│ │ ├── GithubTrendingVM.swift
│ │ └── GithubTrendingUI.swift
│ ├── watchAppApp.swift
│ ├── PushNotificationPayload.apns
│ ├── NotificationController.swift
│ └── ComplicationController.swift
├── Podfile
├── watchApp.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcuserdata
│ │ │ └── anmolverma.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcuserdata
│ │ └── anmolverma.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── watchApp.xcworkspace
│ ├── xcuserdata
│ │ └── anmolverma.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── watchAppUITests
│ ├── watchAppUITestsLaunchTests.swift
│ └── watchAppUITests.swift
└── watchAppTests
│ └── watchAppTests.swift
├── art
├── art1.png
├── art2.png
├── art3.png
├── art4.png
├── art5.png
├── art6.png
└── art7.png
├── shared
├── src
│ ├── androidMain
│ │ ├── AndroidManifest.xml
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── baseio
│ │ │ └── kmm
│ │ │ ├── di
│ │ │ └── platformActual.kt
│ │ │ └── db
│ │ │ └── DriverFactory.kt
│ ├── commonMain
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── baseio
│ │ │ │ └── kmm
│ │ │ │ ├── di
│ │ │ │ ├── platformExpect.kt
│ │ │ │ └── Koin.kt
│ │ │ │ ├── domain
│ │ │ │ ├── usecases
│ │ │ │ │ ├── BaseUseCase.kt
│ │ │ │ │ └── trendingrepos
│ │ │ │ │ │ ├── SaveTrendingReposUseCase.kt
│ │ │ │ │ │ ├── FetchTrendingReposUseCase.kt
│ │ │ │ │ │ └── GetLocalReposUseCase.kt
│ │ │ │ └── model
│ │ │ │ │ └── GithubTrending.kt
│ │ │ │ ├── db
│ │ │ │ ├── DriverFactory.kt
│ │ │ │ └── FlowQuery.kt
│ │ │ │ ├── data
│ │ │ │ ├── network
│ │ │ │ │ ├── GithubTrendingAPI.kt
│ │ │ │ │ └── GithubTrendingAPIImpl.kt
│ │ │ │ └── local
│ │ │ │ │ ├── GithubTrendingLocal.kt
│ │ │ │ │ └── GithubTrendingLocalImpl.kt
│ │ │ │ ├── datamodel
│ │ │ │ └── PraxisDataModel.kt
│ │ │ │ └── features
│ │ │ │ └── trending
│ │ │ │ └── GithubTrendingDataModel.kt
│ │ └── sqldelight
│ │ │ └── db
│ │ │ └── BaseIoDB.sq
│ ├── macosArm64Main
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── baseio
│ │ │ └── kmm
│ │ │ ├── di
│ │ │ └── platformActual.kt
│ │ │ └── db
│ │ │ └── DriverFactory.kt
│ ├── desktopMain
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── baseio
│ │ │ └── kmm
│ │ │ ├── di
│ │ │ └── platformActual.kt
│ │ │ └── db
│ │ │ └── DriverFactory.kt
│ ├── jsMain
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── baseio
│ │ │ └── kmm
│ │ │ ├── di
│ │ │ └── platformActual.kt
│ │ │ └── db
│ │ │ └── DriverFactory.kt
│ ├── iosMain
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── baseio
│ │ │ └── kmm
│ │ │ ├── di
│ │ │ └── platformActual.kt
│ │ │ └── db
│ │ │ └── DriverFactory.kt
│ └── macosX64Main
│ │ └── kotlin
│ │ └── com
│ │ └── baseio
│ │ └── kmm
│ │ ├── di
│ │ └── platformActual.kt
│ │ └── db
│ │ └── DriverFactory.kt
├── shared.podspec
└── build.gradle.kts
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── androidApp
├── src
│ └── main
│ │ ├── res
│ │ ├── drawable
│ │ │ ├── app_widget_preview.png
│ │ │ ├── ic_arrow_right.xml
│ │ │ └── ic_refresh.xml
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ ├── styles.xml
│ │ │ └── themes.xml
│ │ ├── layout
│ │ │ ├── widget_loading.xml
│ │ │ └── activity_main.xml
│ │ └── xml
│ │ │ └── trending_repos_widget_info.xml
│ │ ├── java
│ │ └── com
│ │ │ └── baseio
│ │ │ └── kmm
│ │ │ └── android
│ │ │ ├── ui
│ │ │ └── theme
│ │ │ │ ├── Color.kt
│ │ │ │ ├── Shape.kt
│ │ │ │ ├── Type.kt
│ │ │ │ └── Theme.kt
│ │ │ ├── TrendingReposVM.kt
│ │ │ ├── PraxisApp.kt
│ │ │ ├── TrendingReposListScreen.kt
│ │ │ └── TrendingReposUI.kt
│ │ └── AndroidManifest.xml
└── build.gradle.kts
├── .gitignore
├── webApp
├── src
│ └── jsMain
│ │ ├── resources
│ │ └── index.html
│ │ └── kotlin
│ │ ├── Client.kt
│ │ └── TrendingUI.kt
├── webpack.config.d
│ └── sqljs.js
└── build.gradle.kts
├── settings.gradle.kts
├── gradle.properties
├── README.md
├── gradlew.bat
└── gradlew
/wearOS/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/compose-desktop/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/iosApp/.gitignore:
--------------------------------------------------------------------------------
1 | Pods
2 | Podfile.lock
--------------------------------------------------------------------------------
/macOS/.gitignore:
--------------------------------------------------------------------------------
1 | Pods
2 | Podfile.lock
--------------------------------------------------------------------------------
/watchApp/.gitignore:
--------------------------------------------------------------------------------
1 | Pods
2 | Podfile.lock
--------------------------------------------------------------------------------
/art/art1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/art/art1.png
--------------------------------------------------------------------------------
/art/art2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/art/art2.png
--------------------------------------------------------------------------------
/art/art3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/art/art3.png
--------------------------------------------------------------------------------
/art/art4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/art/art4.png
--------------------------------------------------------------------------------
/art/art5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/art/art5.png
--------------------------------------------------------------------------------
/art/art6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/art/art6.png
--------------------------------------------------------------------------------
/art/art7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/art/art7.png
--------------------------------------------------------------------------------
/shared/src/androidMain/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/iosApp/iosApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
--------------------------------------------------------------------------------
/macOS/macOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/wearOS/src/main/res/values-round/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Hello Round World!
3 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit App/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 | }
--------------------------------------------------------------------------------
/macOS/Podfile:
--------------------------------------------------------------------------------
1 | target 'macOS' do
2 | use_modular_headers!
3 | pod 'shared', :path => '../shared'
4 | pod 'KMPNativeCoroutinesCombine'
5 | end
6 |
--------------------------------------------------------------------------------
/macOS/macOS/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/wearOS/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/wearOS/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/wearOS/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/wearOS/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/wearOS/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/wearOS/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/wearOS/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/wearOS/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/wearOS/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/wearOS/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/androidApp/src/main/res/drawable/app_widget_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/androidApp/src/main/res/drawable/app_widget_preview.png
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/di/platformExpect.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.di
2 |
3 | import org.koin.core.module.Module
4 |
5 |
6 | expect fun platformModule(): Module
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .idea
5 | .DS_Store
6 | /build
7 | */build
8 | /captures
9 | .externalNativeBuild
10 | .cxx
11 | local.properties
12 | kotlin-js-store
--------------------------------------------------------------------------------
/iosApp/Podfile:
--------------------------------------------------------------------------------
1 | target 'iosApp' do
2 | use_frameworks!
3 | platform :ios, '14.1'
4 | pod 'shared', :path => '../shared'
5 | pod 'KMPNativeCoroutinesCombine'
6 | pod 'SDWebImageSwiftUI'
7 | end
8 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/domain/usecases/BaseUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.domain.usecases
2 |
3 | interface BaseUseCase {
4 | suspend fun perform(input: IN?): OUT?
5 | }
--------------------------------------------------------------------------------
/watchApp/Podfile:
--------------------------------------------------------------------------------
1 | target 'watchApp WatchKit Extension' do
2 | use_modular_headers!
3 | pod 'shared', :path => '../shared'
4 | pod 'KMPNativeCoroutinesCombine'
5 | pod 'SDWebImageSwiftUI'
6 | end
7 |
--------------------------------------------------------------------------------
/androidApp/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | TrendingReposUI
3 | Trending Github Repos
4 |
--------------------------------------------------------------------------------
/macOS/macOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/watchApp/watchApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/wearOS/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/iosApp/iosApp.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/macOS/macOS.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/macOS/macOS.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/macOS/macOS/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 |
--------------------------------------------------------------------------------
/watchApp/watchApp.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/watchApp/watchApp.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit App/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 |
--------------------------------------------------------------------------------
/androidApp/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #6200EE
4 | #3700B3
5 | #03DAC5
6 |
--------------------------------------------------------------------------------
/macOS/macOS.xcodeproj/project.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/macOS/macOS.xcodeproj/project.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/db/DriverFactory.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.db
2 |
3 | import com.squareup.sqldelight.db.SqlDriver
4 |
5 | expect class DriverFactory {
6 | fun createDriver(): SqlDriver
7 | suspend fun createDriverBlocking(): SqlDriver
8 | }
9 |
--------------------------------------------------------------------------------
/webApp/src/jsMain/resources/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JS Client
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/iosApp/iosApp/iOSApp.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | @main
4 | struct iOSApp: App {
5 | @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
6 |
7 | var body: some Scene {
8 | WindowGroup {
9 | GithubTrendingScreen()
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/watchApp/watchApp.xcodeproj/project.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oianmol/emploe.baseio.dev/master/watchApp/watchApp.xcodeproj/project.xcworkspace/xcuserdata/anmolverma.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 27 14:55:40 IST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/wearOS/src/main/java/com/baseio/wearos/ui/theme/Color.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.wearos.ui.theme
2 |
3 | import androidx.compose.ui.graphics.Color
4 |
5 | val Purple200 = Color(0xFFBB86FC)
6 | val Purple500 = Color(0xFF6200EE)
7 | val Purple700 = Color(0xFF3700B3)
8 | val Teal200 = Color(0xFF03DAC5)
--------------------------------------------------------------------------------
/androidApp/src/main/java/com/baseio/kmm/android/ui/theme/Color.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.android.ui.theme
2 |
3 | import androidx.compose.ui.graphics.Color
4 |
5 | val Purple200 = Color(0xFFBB86FC)
6 | val Purple500 = Color(0xFF6200EE)
7 | val Purple700 = Color(0xFF3700B3)
8 | val Teal200 = Color(0xFF03DAC5)
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/data/network/GithubTrendingAPI.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.data.network
2 |
3 | import com.baseio.kmm.domain.model.GithubReposItem
4 |
5 | interface GithubTrendingAPI {
6 | suspend fun getTrendingRepos(
7 | query: String
8 | ): List
9 | }
--------------------------------------------------------------------------------
/macOS/macOS.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macOS/macOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/watchApp/watchApp.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/watchApp/watchApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macOS/macOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google()
4 | gradlePluginPortal()
5 | mavenCentral()
6 | }
7 | }
8 |
9 | rootProject.name = "BaseiOKMM"
10 | include(":androidApp")
11 | include(":shared")
12 | include(":watchApp")
13 | include(":wearOS")
14 | include(":webApp")
15 | include(":compose-desktop")
--------------------------------------------------------------------------------
/watchApp/watchApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/androidApp/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/shared/src/macosArm64Main/kotlin/com/baseio/kmm/di/platformActual.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.di
2 |
3 | import com.baseio.kmm.db.DriverFactory
4 | import org.koin.dsl.module
5 | import io.ktor.client.engine.ios.*
6 |
7 | actual fun platformModule() = module {
8 | single { Ios.create() }
9 | single {
10 | DriverFactory().createDriver()
11 | }
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/shared/src/desktopMain/kotlin/com/baseio/kmm/di/platformActual.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.di
2 |
3 | import com.baseio.kmm.db.DriverFactory
4 | import io.ktor.client.engine.java.*
5 | import org.koin.dsl.module
6 |
7 | actual fun platformModule() = module {
8 | single { Java.create() }
9 | single {
10 | DriverFactory().createDriver()
11 | }
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/shared/src/androidMain/kotlin/com/baseio/kmm/di/platformActual.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.di
2 |
3 | import com.baseio.kmm.db.DriverFactory
4 | import org.koin.dsl.module
5 | import io.ktor.client.engine.android.*
6 |
7 | actual fun platformModule() = module {
8 | single { Android.create() }
9 | single {
10 | DriverFactory(get()).createDriver()
11 | }
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/wearOS/src/main/java/com/baseio/wearos/ui/theme/Shape.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.wearos.ui.theme
2 |
3 | import androidx.compose.foundation.shape.RoundedCornerShape
4 | import androidx.compose.material.Shapes
5 | import androidx.compose.ui.unit.dp
6 |
7 | val Shapes = Shapes(
8 | small = RoundedCornerShape(4.dp),
9 | medium = RoundedCornerShape(4.dp),
10 | large = RoundedCornerShape(0.dp)
11 | )
--------------------------------------------------------------------------------
/androidApp/src/main/java/com/baseio/kmm/android/ui/theme/Shape.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.android.ui.theme
2 |
3 | import androidx.compose.foundation.shape.RoundedCornerShape
4 | import androidx.compose.material.Shapes
5 | import androidx.compose.ui.unit.dp
6 |
7 | val Shapes = Shapes(
8 | small = RoundedCornerShape(4.dp),
9 | medium = RoundedCornerShape(4.dp),
10 | large = RoundedCornerShape(0.dp)
11 | )
--------------------------------------------------------------------------------
/wearOS/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PraxisKmm
3 |
7 | Hello Square World!
8 | TrendingReposUI
9 |
--------------------------------------------------------------------------------
/androidApp/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/macOS/macOS/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // macOS
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct ContentView: View {
11 | var body: some View {
12 | Text("Hello, world!")
13 | .padding()
14 | }
15 | }
16 |
17 | struct ContentView_Previews: PreviewProvider {
18 | static var previews: some View {
19 | ContentView()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/domain/model/GithubTrending.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.domain.model
2 |
3 | import kotlinx.serialization.Serializable
4 |
5 | @Serializable
6 | data class GithubReposItem(
7 | val author: String? = null,
8 | val avatar: String? = null,
9 | val description: String? = null,
10 | val language: String? = null,
11 | val name: String? = null,
12 | val url: String? = null
13 | )
14 |
15 |
--------------------------------------------------------------------------------
/shared/src/jsMain/kotlin/com/baseio/kmm/di/platformActual.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.di
2 |
3 | import com.baseio.kmm.db.DriverFactory
4 | import org.koin.dsl.module
5 | import io.ktor.client.engine.js.*
6 |
7 | actual fun platformModule() = module {
8 | single { Js.create() }
9 | single {
10 | DriverFactory().createDriver() // this never gets called for js since sqldriver is async and koin doesn't support that yet.
11 | }
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/data/local/GithubTrendingLocal.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.data.local
2 |
3 | import com.baseio.kmm.domain.model.GithubReposItem
4 | import com.squareup.sqldelight.db.SqlDriver
5 | import db.Trending_repos
6 | import kotlinx.coroutines.flow.Flow
7 |
8 | interface GithubTrendingLocal {
9 | var driver: SqlDriver?
10 | fun saveRepos(input: List)
11 | fun getAll(): Flow>
12 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #Gradle
2 | org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
3 |
4 | #Kotlin
5 | kotlin.code.style=official
6 |
7 | #Android
8 | android.useAndroidX=true
9 | kotlinVersion=1.6.10
10 | kotlin.native.binary.memoryModel=experimental
11 | kotlin.native.binary.freezing=disabled
12 | #MPP
13 | kotlin.mpp.enableGranularSourceSetsMetadata=true
14 | kotlin.native.enableDependencyPropagation=false
15 | kotlin.mpp.enableCInteropCommonization=true
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/datamodel/PraxisDataModel.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.datamodel
2 |
3 | import kotlinx.coroutines.CoroutineScope
4 | import kotlinx.coroutines.Dispatchers
5 | import kotlinx.coroutines.SupervisorJob
6 |
7 | abstract class PraxisDataModel {
8 | protected val dataModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
9 |
10 |
11 | abstract fun activate()
12 | abstract fun destroy()
13 | abstract fun refresh()
14 | }
--------------------------------------------------------------------------------
/macOS/macOS.xcodeproj/xcuserdata/anmolverma.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | macOS.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 4
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/shared/src/iosMain/kotlin/com/baseio/kmm/di/platformActual.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.di
2 |
3 | import com.baseio.kmm.db.DriverFactory
4 | import com.squareup.sqldelight.db.SqlDriver
5 | import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
6 | import org.koin.dsl.module
7 | import io.ktor.client.engine.ios.*
8 |
9 | actual fun platformModule() = module {
10 | single { Ios.create() }
11 | single {
12 | DriverFactory().createDriver()
13 | }
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "scale" : "2x"
6 | },
7 | {
8 | "idiom" : "watch",
9 | "scale" : "2x",
10 | "screen-width" : ">183"
11 | }
12 | ],
13 | "info" : {
14 | "author" : "xcode",
15 | "version" : 1
16 | },
17 | "properties" : {
18 | "auto-scaling" : "auto"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "scale" : "2x"
6 | },
7 | {
8 | "idiom" : "watch",
9 | "scale" : "2x",
10 | "screen-width" : ">183"
11 | }
12 | ],
13 | "info" : {
14 | "author" : "xcode",
15 | "version" : 1
16 | },
17 | "properties" : {
18 | "auto-scaling" : "auto"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/androidApp/src/main/res/layout/widget_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcodeproj/xcuserdata/anmolverma.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | iosApp.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 6
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/shared/src/macosX64Main/kotlin/com/baseio/kmm/di/platformActual.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.di
2 |
3 | import com.baseio.kmm.db.DriverFactory
4 | import com.squareup.sqldelight.db.SqlDriver
5 | import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
6 | import org.koin.dsl.module
7 | import io.ktor.client.engine.ios.*
8 |
9 | actual fun platformModule() = module {
10 | single { Ios.create() }
11 | single {
12 | DriverFactory().createDriver()
13 | }
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "scale" : "2x"
6 | },
7 | {
8 | "idiom" : "watch",
9 | "scale" : "2x",
10 | "screen-width" : ">183"
11 | }
12 | ],
13 | "info" : {
14 | "author" : "xcode",
15 | "version" : 1
16 | },
17 | "properties" : {
18 | "auto-scaling" : "auto"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/NotificationView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationView.swift
3 | // watchApp WatchKit Extension
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import SwiftUI
9 |
10 | struct NotificationView: View {
11 | var body: some View {
12 | Text("Hello, World!")
13 | }
14 | }
15 |
16 | struct NotificationView_Previews: PreviewProvider {
17 | static var previews: some View {
18 | NotificationView()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/webApp/webpack.config.d/sqljs.js:
--------------------------------------------------------------------------------
1 |
2 | config.resolve.fallback = {
3 | fs: false,
4 | path: false,
5 | crypto: false,
6 | };
7 |
8 | const CopyWebpackPlugin = require('copy-webpack-plugin');
9 | config.plugins.push(
10 | new CopyWebpackPlugin({
11 | patterns: [
12 | {
13 | from: '../../node_modules/sql.js/dist/sql-wasm.wasm',
14 | to: '../../../webApp/build/distributions'
15 | }
16 | ]
17 | })
18 | );
--------------------------------------------------------------------------------
/androidApp/src/main/res/drawable/ic_arrow_right.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "scale" : "2x"
6 | },
7 | {
8 | "idiom" : "watch",
9 | "scale" : "2x",
10 | "screen-width" : ">183"
11 | }
12 | ],
13 | "info" : {
14 | "author" : "xcode",
15 | "version" : 1
16 | },
17 | "properties" : {
18 | "auto-scaling" : "auto"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/macOS/macOS/macOS.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 | com.apple.security.network.client
10 |
11 | com.apple.security.network.server
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/shared/src/commonMain/sqldelight/db/BaseIoDB.sq:
--------------------------------------------------------------------------------
1 | CREATE TABLE trending_repos(
2 | uid TEXT NOT NULL PRIMARY KEY,
3 | author TEXT,
4 | avatar TEXT,
5 | description TEXT,
6 | language TEXT,
7 | name TEXT,
8 | url TEXT
9 | );
10 |
11 | insertRepo:
12 | INSERT OR REPLACE INTO trending_repos(uid,author,avatar,description,language,name,url) VALUES(?,?,?,?,?,?,?);
13 |
14 | selectAllRepos:
15 | SELECT * FROM trending_repos ORDER BY name ASC;
16 |
17 | deleteAllRepos:
18 | DELETE FROM trending_repos;
--------------------------------------------------------------------------------
/shared/src/iosMain/kotlin/com/baseio/kmm/db/DriverFactory.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.db
2 |
3 | import com.squareup.sqldelight.db.SqlDriver
4 | import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
5 |
6 | actual class DriverFactory {
7 | actual fun createDriver(): SqlDriver {
8 | return NativeSqliteDriver(BaseIoDB.Schema, "baseio.db")
9 | }
10 |
11 | actual suspend fun createDriverBlocking(): SqlDriver {
12 | return NativeSqliteDriver(BaseIoDB.Schema, "baseio.db")
13 | }
14 | }
--------------------------------------------------------------------------------
/macOS/macOS/macOSApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // macOSApp.swift
3 | // macOS
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import SwiftUI
9 | import shared
10 |
11 | let sharedComponent = SharedComponent()
12 | let useCasesComponent = UseCasesComponent()
13 |
14 | @main
15 | struct macOSApp: App {
16 | init() {
17 | KoinKt.doInitSharedDependencies()
18 | }
19 |
20 | var body: some Scene {
21 | WindowGroup {
22 | GithubTrendingScreen()
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/shared/src/macosArm64Main/kotlin/com/baseio/kmm/db/DriverFactory.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.db
2 |
3 | import com.squareup.sqldelight.db.SqlDriver
4 | import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
5 |
6 | actual class DriverFactory {
7 | actual fun createDriver(): SqlDriver {
8 | return NativeSqliteDriver(BaseIoDB.Schema, "baseio.db")
9 | }
10 |
11 | actual suspend fun createDriverBlocking(): SqlDriver {
12 | return NativeSqliteDriver(BaseIoDB.Schema, "baseio.db")
13 | }
14 | }
--------------------------------------------------------------------------------
/shared/src/macosX64Main/kotlin/com/baseio/kmm/db/DriverFactory.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.db
2 |
3 | import com.squareup.sqldelight.db.SqlDriver
4 | import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
5 |
6 | actual class DriverFactory {
7 | actual fun createDriver(): SqlDriver {
8 | return NativeSqliteDriver(BaseIoDB.Schema, "baseio.db")
9 | }
10 |
11 | actual suspend fun createDriverBlocking(): SqlDriver {
12 | return NativeSqliteDriver(BaseIoDB.Schema, "baseio.db")
13 | }
14 | }
--------------------------------------------------------------------------------
/wearOS/src/main/java/com/baseio/wearos/PraxisApp.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.wearos
2 |
3 | import android.app.Application
4 | import com.baseio.kmm.di.SharedComponent
5 | import com.baseio.kmm.di.UseCasesComponent
6 | import com.baseio.kmm.di.initSqlDelightExperimentalDependencies
7 |
8 | val sharedComponent = SharedComponent()
9 | val useCasesComponent = UseCasesComponent()
10 |
11 | class PraxisApp : Application() {
12 | override fun onCreate() {
13 | super.onCreate()
14 | initSqlDelightExperimentalDependencies()
15 | }
16 | }
--------------------------------------------------------------------------------
/shared/src/jsMain/kotlin/com/baseio/kmm/db/DriverFactory.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.db
2 |
3 | import com.squareup.sqldelight.db.SqlDriver
4 | import com.squareup.sqldelight.drivers.sqljs.initSqlDriver
5 | import kotlinx.coroutines.await
6 |
7 | actual class DriverFactory {
8 | actual fun createDriver(): SqlDriver {
9 | throw RuntimeException("call createDriverBlocking")
10 | }
11 |
12 | actual suspend fun createDriverBlocking(): SqlDriver {
13 | return initSqlDriver(BaseIoDB.Schema).await()
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/androidApp/src/main/res/xml/trending_repos_widget_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/data/network/GithubTrendingAPIImpl.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.data.network
2 |
3 | import com.baseio.kmm.domain.model.GithubReposItem
4 | import io.ktor.client.*
5 | import io.ktor.client.request.*
6 |
7 | const val BASE_URL = "https://gtrend.yapie.me"
8 |
9 | class GithubTrendingAPIImpl(private val httpClient: HttpClient) : GithubTrendingAPI {
10 | override suspend fun getTrendingRepos(query: String): List {
11 | return httpClient.get("$BASE_URL/repositories?language=$query")
12 | }
13 | }
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSExtension
6 |
7 | NSExtensionAttributes
8 |
9 | WKAppBundleIdentifier
10 | orgIdentifier.iosApp.watchApp.watchkitapp
11 |
12 | NSExtensionPointIdentifier
13 | com.apple.watchkit
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/macOS/macOS/githubtrending/UiRepo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UiRepo.swift
3 | // iosApp
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | // Copyright © 2021 orgName. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class UIRepo: Identifiable {
12 | let author, name: String?
13 | let avatar: String?
14 | let url: String?
15 |
16 |
17 | init(author: String?, name: String?, avatar: String?, url: String?) {
18 | self.author = author
19 | self.name = name
20 | self.avatar = avatar
21 | self.url = url
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/iosApp/iosApp/githubtrending/UiRepo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UiRepo.swift
3 | // iosApp
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | // Copyright © 2021 orgName. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class UIRepo: Identifiable {
12 | let author, name: String?
13 | let avatar: String?
14 | let url: String?
15 |
16 |
17 | init(author: String?, name: String?, avatar: String?, url: String?) {
18 | self.author = author
19 | self.name = name
20 | self.avatar = avatar
21 | self.url = url
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "scale" : "2x"
6 | },
7 | {
8 | "idiom" : "watch",
9 | "scale" : "2x",
10 | "screen-width" : "<=145"
11 | },
12 | {
13 | "idiom" : "watch",
14 | "scale" : "2x",
15 | "screen-width" : ">183"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "auto-scaling" : "auto"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "scale" : "2x"
6 | },
7 | {
8 | "idiom" : "watch",
9 | "scale" : "2x",
10 | "screen-width" : "<=145"
11 | },
12 | {
13 | "idiom" : "watch",
14 | "scale" : "2x",
15 | "screen-width" : ">183"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "auto-scaling" : "auto"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "scale" : "2x"
6 | },
7 | {
8 | "idiom" : "watch",
9 | "scale" : "2x",
10 | "screen-width" : "<=145"
11 | },
12 | {
13 | "idiom" : "watch",
14 | "scale" : "2x",
15 | "screen-width" : ">183"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "auto-scaling" : "auto"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "scale" : "2x"
6 | },
7 | {
8 | "idiom" : "watch",
9 | "scale" : "2x",
10 | "screen-width" : "<=145"
11 | },
12 | {
13 | "idiom" : "watch",
14 | "scale" : "2x",
15 | "screen-width" : ">183"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "auto-scaling" : "auto"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/shared/src/androidMain/kotlin/com/baseio/kmm/db/DriverFactory.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.db
2 |
3 | import android.content.Context
4 | import com.squareup.sqldelight.android.AndroidSqliteDriver
5 | import com.squareup.sqldelight.db.SqlDriver
6 |
7 | actual class DriverFactory(private val context: Context) {
8 | actual fun createDriver(): SqlDriver {
9 | return AndroidSqliteDriver(BaseIoDB.Schema, context, "baseio.db")
10 | }
11 |
12 | actual suspend fun createDriverBlocking(): SqlDriver {
13 | return AndroidSqliteDriver(BaseIoDB.Schema, context, "baseio.db")
14 | }
15 | }
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/githubtrending/UiRepo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UiRepo.swift
3 | // watchApp WatchKit Extension
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | import Foundation
12 |
13 | class UIRepo: Identifiable {
14 | let author, name: String?
15 | let avatar: String?
16 | let url: String?
17 |
18 |
19 | init(author: String?, name: String?, avatar: String?, url: String?) {
20 | self.author = author
21 | self.name = name
22 | self.avatar = avatar
23 | self.url = url
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/domain/usecases/trendingrepos/SaveTrendingReposUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.domain.usecases.trendingrepos
2 |
3 | import com.baseio.kmm.data.local.GithubTrendingLocal
4 | import com.baseio.kmm.domain.model.GithubReposItem
5 | import com.baseio.kmm.domain.usecases.BaseUseCase
6 |
7 | class SaveTrendingReposUseCase(private val githubTrendingLocal: GithubTrendingLocal) :
8 | BaseUseCase, Unit> {
9 | override suspend fun perform(input: List?) {
10 | return githubTrendingLocal.saveRepos(input!!)
11 | }
12 | }
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "scale" : "2x"
6 | },
7 | {
8 | "idiom" : "watch",
9 | "scale" : "2x",
10 | "screen-width" : "<=145"
11 | },
12 | {
13 | "idiom" : "watch",
14 | "scale" : "2x",
15 | "screen-width" : ">183"
16 | }
17 | ],
18 | "info" : {
19 | "author" : "xcode",
20 | "version" : 1
21 | },
22 | "properties" : {
23 | "auto-scaling" : "auto"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/androidApp/src/main/res/drawable/ic_refresh.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/domain/usecases/trendingrepos/FetchTrendingReposUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.domain.usecases.trendingrepos
2 |
3 | import com.baseio.kmm.data.network.GithubTrendingAPI
4 | import com.baseio.kmm.domain.model.GithubReposItem
5 | import com.baseio.kmm.domain.usecases.BaseUseCase
6 |
7 | class FetchTrendingReposUseCase(private val githubTrendingAPI: GithubTrendingAPI) :
8 | BaseUseCase> {
9 | override suspend fun perform(input: String?): List {
10 | return githubTrendingAPI.getTrendingRepos(input!!)
11 | }
12 | }
--------------------------------------------------------------------------------
/compose-desktop/src/jvmMain/kotlin/TrendingReposVM.kt:
--------------------------------------------------------------------------------
1 | import androidx.compose.runtime.MutableState
2 | import androidx.compose.runtime.mutableStateOf
3 | import com.baseio.kmm.features.trending.GithubTrendingDataModel
4 | import kotlinx.coroutines.flow.MutableStateFlow
5 |
6 | class TrendingReposVM {
7 |
8 | var uiState = mutableStateOf(GithubTrendingDataModel.EmptyState)
9 | private set
10 |
11 | private val trendingDataModel = GithubTrendingDataModel(onDataState = { stateNew ->
12 | uiState.value = stateNew
13 | })
14 |
15 | init {
16 | trendingDataModel.activate()
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/shared/src/desktopMain/kotlin/com/baseio/kmm/db/DriverFactory.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.db
2 |
3 | import com.squareup.sqldelight.db.SqlDriver
4 | import com.squareup.sqldelight.sqlite.driver.JdbcSqliteDriver
5 |
6 | actual class DriverFactory {
7 | actual fun createDriver(): SqlDriver {
8 | return JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY).also {
9 | BaseIoDB.Schema.create(it)
10 | }
11 | }
12 |
13 | actual suspend fun createDriverBlocking(): SqlDriver {
14 | return JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY).also {
15 | BaseIoDB.Schema.create(it)
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/compose-desktop/src/jvmMain/kotlin/Main.kt:
--------------------------------------------------------------------------------
1 | import androidx.compose.material.MaterialTheme
2 | import androidx.compose.desktop.ui.tooling.preview.Preview
3 | import androidx.compose.runtime.Composable
4 | import androidx.compose.ui.window.Window
5 | import androidx.compose.ui.window.application
6 | import com.baseio.kmm.di.initSharedDependencies
7 |
8 | @Composable
9 | @Preview
10 | fun App() {
11 | MaterialTheme {
12 | TrendingReposListScreen(TrendingReposVM())
13 | }
14 | }
15 |
16 | fun main() = application {
17 | initSharedDependencies()
18 | Window(onCloseRequest = ::exitApplication) {
19 | App()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/wearOS/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 0dp
8 |
9 |
14 | 5dp
15 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcworkspace/xcuserdata/anmolverma.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildLocationStyle
6 | UseAppPreferences
7 | CustomBuildLocationType
8 | RelativeToDerivedData
9 | DerivedDataLocationStyle
10 | Default
11 | IssueFilterStyle
12 | ShowActiveSchemeOnly
13 | LiveSourceIssuesEnabled
14 |
15 | ShowSharedSchemesAutomaticallyEnabled
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/watchAppApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // watchAppApp.swift
3 | // watchApp WatchKit Extension
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import SwiftUI
9 | import shared
10 |
11 | let sharedComponent = SharedComponent()
12 | let useCasesComponent = UseCasesComponent()
13 |
14 | @main
15 | struct watchAppApp: App {
16 | init() {
17 | KoinKt.doInitSharedDependencies()
18 | }
19 |
20 | @SceneBuilder var body: some Scene {
21 | WindowGroup {
22 | NavigationView {
23 | GithubTrendingScreen()
24 | }
25 | }
26 |
27 |
28 | WKNotificationScene(controller: NotificationController.self, category: "myCategory")
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/watchApp/watchApp.xcodeproj/xcuserdata/anmolverma.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | watchApp WatchKit App (Complication).xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 2
11 |
12 | watchApp WatchKit App (Notification).xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 1
16 |
17 | watchApp WatchKit App.xcscheme_^#shared#^_
18 |
19 | orderHint
20 | 0
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/webApp/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | WebAppPlugins.plugins.forEach { dependency ->
3 | kotlin(dependency)
4 | }
5 | }
6 |
7 | kotlin {
8 | js(IR) {
9 | browser()
10 | binaries.executable()
11 | }
12 |
13 | sourceSets {
14 | val jsMain by getting {
15 | dependencies {
16 | implementation(project(":shared"))
17 | WebAppDependencies.implementation.forEach(::implementation)
18 | WebAppDependencies.kotlin.map { dependency ->
19 | kotlin(dependency)
20 | }.forEach(::implementation)
21 | WebAppDependencies.npm.map { (dependency, version) ->
22 | npm(dependency, version)
23 | }.forEach(::implementation)
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/wearOS/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/domain/usecases/trendingrepos/GetLocalReposUseCase.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.domain.usecases.trendingrepos
2 |
3 | import com.baseio.kmm.data.local.GithubTrendingLocal
4 | import com.baseio.kmm.domain.model.GithubReposItem
5 | import com.baseio.kmm.domain.usecases.BaseUseCase
6 | import kotlinx.coroutines.flow.Flow
7 | import kotlinx.coroutines.flow.map
8 |
9 | class GetLocalReposUseCase(private val githubTrendingLocal: GithubTrendingLocal) :
10 | BaseUseCase>> {
11 | override suspend fun perform(input: Unit?): Flow> {
12 | return githubTrendingLocal.getAll().map {
13 | it.map {
14 | GithubReposItem(it.author, it.avatar, it.description, it.language, it.name, it.url)
15 | }
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/androidApp/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
--------------------------------------------------------------------------------
/wearOS/src/main/java/com/baseio/wearos/ui/theme/Type.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.wearos.ui.theme
2 |
3 | import androidx.compose.material.Typography
4 | import androidx.compose.ui.text.TextStyle
5 | import androidx.compose.ui.text.font.FontFamily
6 | import androidx.compose.ui.text.font.FontWeight
7 | import androidx.compose.ui.unit.sp
8 |
9 | // Set of Material typography styles to start with
10 | val Typography = Typography(
11 | body1 = TextStyle(
12 | fontFamily = FontFamily.Default,
13 | fontWeight = FontWeight.Normal,
14 | fontSize = 16.sp
15 | )
16 | /* Other default text styles to override
17 | button = TextStyle(
18 | fontFamily = FontFamily.Default,
19 | fontWeight = FontWeight.W500,
20 | fontSize = 14.sp
21 | ),
22 | caption = TextStyle(
23 | fontFamily = FontFamily.Default,
24 | fontWeight = FontWeight.Normal,
25 | fontSize = 12.sp
26 | )
27 | */
28 | )
--------------------------------------------------------------------------------
/androidApp/src/main/java/com/baseio/kmm/android/ui/theme/Type.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.android.ui.theme
2 |
3 | import androidx.compose.material.Typography
4 | import androidx.compose.ui.text.TextStyle
5 | import androidx.compose.ui.text.font.FontFamily
6 | import androidx.compose.ui.text.font.FontWeight
7 | import androidx.compose.ui.unit.sp
8 |
9 | // Set of Material typography styles to start with
10 | val Typography = Typography(
11 | body1 = TextStyle(
12 | fontFamily = FontFamily.Default,
13 | fontWeight = FontWeight.Normal,
14 | fontSize = 16.sp
15 | )
16 | /* Other default text styles to override
17 | button = TextStyle(
18 | fontFamily = FontFamily.Default,
19 | fontWeight = FontWeight.W500,
20 | fontSize = 14.sp
21 | ),
22 | caption = TextStyle(
23 | fontFamily = FontFamily.Default,
24 | fontWeight = FontWeight.Normal,
25 | fontSize = 12.sp
26 | )
27 | */
28 | )
--------------------------------------------------------------------------------
/macOS/macOSUITests/macOSUITestsLaunchTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // macOSUITestsLaunchTests.swift
3 | // macOSUITests
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import XCTest
9 |
10 | class macOSUITestsLaunchTests: XCTestCase {
11 |
12 | override class var runsForEachTargetApplicationUIConfiguration: Bool {
13 | true
14 | }
15 |
16 | override func setUpWithError() throws {
17 | continueAfterFailure = false
18 | }
19 |
20 | func testLaunch() throws {
21 | let app = XCUIApplication()
22 | app.launch()
23 |
24 | // Insert steps here to perform after app launch but before taking a screenshot,
25 | // such as logging into a test account or navigating somewhere in the app
26 |
27 | let attachment = XCTAttachment(screenshot: app.screenshot())
28 | attachment.name = "Launch Screen"
29 | attachment.lifetime = .keepAlways
30 | add(attachment)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/watchApp/watchAppUITests/watchAppUITestsLaunchTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // watchAppUITestsLaunchTests.swift
3 | // watchAppUITests
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import XCTest
9 |
10 | class watchAppUITestsLaunchTests: XCTestCase {
11 |
12 | override class var runsForEachTargetApplicationUIConfiguration: Bool {
13 | true
14 | }
15 |
16 | override func setUpWithError() throws {
17 | continueAfterFailure = false
18 | }
19 |
20 | func testLaunch() throws {
21 | let app = XCUIApplication()
22 | app.launch()
23 |
24 | // Insert steps here to perform after app launch but before taking a screenshot,
25 | // such as logging into a test account or navigating somewhere in the app
26 |
27 | let attachment = XCTAttachment(screenshot: app.screenshot())
28 | attachment.name = "Launch Screen"
29 | attachment.lifetime = .keepAlways
30 | add(attachment)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/androidApp/src/main/java/com/baseio/kmm/android/TrendingReposVM.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.android
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.viewModelScope
5 | import com.baseio.kmm.features.trending.GithubTrendingDataModel
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.flow.MutableStateFlow
8 | import kotlinx.coroutines.launch
9 |
10 | class TrendingReposVM : ViewModel() {
11 |
12 | var uiState = MutableStateFlow(GithubTrendingDataModel.EmptyState)
13 | private set
14 |
15 | private val trendingDataModel = GithubTrendingDataModel(onDataState = { stateNew ->
16 | viewModelScope.launch {
17 | uiState.emit(stateNew)
18 | }
19 | })
20 |
21 | init {
22 | viewModelScope.launch {
23 | delay(1500)
24 | trendingDataModel.activate()
25 | }
26 | }
27 |
28 | override fun onCleared() {
29 | super.onCleared()
30 | trendingDataModel.destroy()
31 | }
32 | }
33 |
34 |
35 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/PushNotificationPayload.apns:
--------------------------------------------------------------------------------
1 | {
2 | "aps": {
3 | "alert": {
4 | "body": "Test message",
5 | "title": "Optional title",
6 | "subtitle": "Optional subtitle"
7 | },
8 | "category": "myCategory",
9 | "thread-id": "5280"
10 | },
11 |
12 | "WatchKit Simulator Actions": [
13 | {
14 | "title": "First Button",
15 | "identifier": "firstButtonAction"
16 | }
17 | ],
18 |
19 | "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App."
20 | }
21 |
--------------------------------------------------------------------------------
/wearOS/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/wearOS/src/main/java/com/baseio/wearos/TrendingReposUI.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.wearos
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import androidx.compose.material.*
7 | import androidx.compose.runtime.Composable
8 | import androidx.compose.ui.graphics.Color
9 | import com.baseio.wearos.ui.theme.BaseiOKMMTheme
10 |
11 | class TrendingReposUI : ComponentActivity() {
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | val viewModel = TrendingReposVM(application)
15 | setContent {
16 | BaseiOKMMTheme {
17 | val materialBlue700 = Color(0xFF1976D2)
18 | // A surface container using the 'background' color from the theme
19 | Surface(color = MaterialTheme.colors.background) {
20 | Scaffold(
21 | content = {
22 | TrendingReposListScreen(viewModel)
23 | },
24 | )
25 | }
26 | }
27 | }
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/androidApp/src/main/java/com/baseio/kmm/android/PraxisApp.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.android
2 |
3 | import android.app.Application
4 | import com.baseio.kmm.db.DriverFactory
5 | import com.baseio.kmm.di.SharedComponent
6 | import com.baseio.kmm.di.UseCasesComponent
7 | import com.baseio.kmm.di.initSqlDelightExperimentalDependencies
8 | import kotlinx.coroutines.GlobalScope
9 | import kotlinx.coroutines.launch
10 |
11 | val sharedComponent = SharedComponent()
12 | val useCasesComponent = UseCasesComponent()
13 |
14 | class PraxisApp : Application() {
15 | override fun onCreate() {
16 | super.onCreate()
17 | initSqlDelightExperimentalDependencies()
18 | GlobalScope.launch {
19 | precheckSqlite()
20 | }
21 | }
22 |
23 | private suspend fun precheckSqlite() {
24 | if (sharedComponent.provideGithubTrendingLocal().driver == null) {
25 | val driver = DriverFactory(context = this).createDriverBlocking()
26 | sharedComponent.provideGithubTrendingLocal().driver = driver
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/androidApp/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/iosApp/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - KMPNativeCoroutinesCombine (0.9.0):
3 | - KMPNativeCoroutinesCore (= 0.9.0)
4 | - KMPNativeCoroutinesCore (0.9.0)
5 | - SDWebImage (5.12.1):
6 | - SDWebImage/Core (= 5.12.1)
7 | - SDWebImage/Core (5.12.1)
8 | - SDWebImageSwiftUI (2.0.2):
9 | - SDWebImage (~> 5.10)
10 | - shared (1.0)
11 |
12 | DEPENDENCIES:
13 | - KMPNativeCoroutinesCombine
14 | - SDWebImageSwiftUI
15 | - shared (from `../shared`)
16 |
17 | SPEC REPOS:
18 | trunk:
19 | - KMPNativeCoroutinesCombine
20 | - KMPNativeCoroutinesCore
21 | - SDWebImage
22 | - SDWebImageSwiftUI
23 |
24 | EXTERNAL SOURCES:
25 | shared:
26 | :path: "../shared"
27 |
28 | SPEC CHECKSUMS:
29 | KMPNativeCoroutinesCombine: 3a3c39852cf9fcb764b97ac604bd1cfacdd720c7
30 | KMPNativeCoroutinesCore: a9abca92a371f0c1af62bfb06c94c943ad515114
31 | SDWebImage: 4dc3e42d9ec0c1028b960a33ac6b637bb432207b
32 | SDWebImageSwiftUI: 8a3923c95108312b03a599ec1498754af55a6819
33 | shared: 7b4d6aa8aa7ada5f9dae3229e2524d316cb9f063
34 |
35 | PODFILE CHECKSUM: 3b06299be4209d7c4ba59dbfe9a4c75924eba947
36 |
37 | COCOAPODS: 1.11.2
38 |
--------------------------------------------------------------------------------
/compose-desktop/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import org.jetbrains.compose.compose
2 | import org.jetbrains.compose.desktop.application.dsl.TargetFormat
3 |
4 | plugins {
5 | kotlin("multiplatform")
6 | id("org.jetbrains.compose") version ComposeDesktopDependencyVersions.composeDesktopWeb
7 | }
8 |
9 | group = "com.mutualmobile"
10 | version = "1.0"
11 |
12 | repositories {
13 | mavenCentral()
14 | maven(url = "https://maven.pkg.jetbrains.space/public/p/compose/dev")
15 | }
16 |
17 |
18 | kotlin {
19 | jvm {
20 | compilations.all {
21 | kotlinOptions.jvmTarget = "11"
22 | }
23 | withJava()
24 | }
25 | sourceSets {
26 | val jvmMain by getting {
27 | dependencies {
28 | implementation(project(":shared"))
29 | implementation(compose.desktop.currentOs)
30 | }
31 | }
32 | val jvmTest by getting
33 | }
34 | }
35 |
36 | compose.desktop {
37 | application {
38 | mainClass = "MainKt"
39 | nativeDistributions {
40 | targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
41 | packageName = "jvm"
42 | packageVersion = "1.0.0"
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/NotificationController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationController.swift
3 | // watchApp WatchKit Extension
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import WatchKit
9 | import SwiftUI
10 | import UserNotifications
11 |
12 | class NotificationController: WKUserNotificationHostingController {
13 |
14 | override var body: NotificationView {
15 | return NotificationView()
16 | }
17 |
18 | override func willActivate() {
19 | // This method is called when watch view controller is about to be visible to user
20 | super.willActivate()
21 | }
22 |
23 | override func didDeactivate() {
24 | // This method is called when watch view controller is no longer visible
25 | super.didDeactivate()
26 | }
27 |
28 | override func didReceive(_ notification: UNNotification) {
29 | // This method is called when a notification needs to be presented.
30 | // Implement it if you use a dynamic notification interface.
31 | // Populate your dynamic notification interface as quickly as possible.
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/webApp/src/jsMain/kotlin/Client.kt:
--------------------------------------------------------------------------------
1 | import com.baseio.kmm.db.DriverFactory
2 | import com.baseio.kmm.di.SharedComponent
3 | import com.baseio.kmm.di.UseCasesComponent
4 | import com.baseio.kmm.di.initSqlDelightExperimentalDependencies
5 | import react.dom.render
6 | import kotlinx.browser.document
7 | import kotlinx.browser.window
8 |
9 | val sharedComponent = SharedComponent()
10 | val useCasesComponent = UseCasesComponent()
11 |
12 | fun main() {
13 | initSqlDelightExperimentalDependencies()
14 | window.onload = { _ ->
15 | val rootDiv = document.getElementById("root")
16 | render(rootDiv!!) {
17 | child(TrendingUI)
18 | }
19 | }
20 | }
21 |
22 | suspend fun setupDriver() {
23 | sharedComponent.provideGithubTrendingLocal().driver?.let {} ?: run {
24 | setupDriverInternal()
25 | }
26 |
27 | }
28 |
29 | private suspend fun setupDriverInternal() {
30 | try {
31 | val driver = DriverFactory().createDriverBlocking()
32 | val trendingLocal = sharedComponent.provideGithubTrendingLocal()
33 | trendingLocal.driver = driver
34 | } catch (ex: Exception) {
35 | console.log(ex.message)
36 | console.log("Exception happened here.")
37 | console.log(ex)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/macOS/macOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "scale" : "1x",
6 | "size" : "16x16"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "scale" : "2x",
11 | "size" : "16x16"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "scale" : "1x",
16 | "size" : "32x32"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "scale" : "2x",
21 | "size" : "32x32"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "scale" : "1x",
26 | "size" : "128x128"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "scale" : "2x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "scale" : "1x",
36 | "size" : "256x256"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "scale" : "2x",
41 | "size" : "256x256"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "scale" : "1x",
46 | "size" : "512x512"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "scale" : "2x",
51 | "size" : "512x512"
52 | }
53 | ],
54 | "info" : {
55 | "author" : "xcode",
56 | "version" : 1
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/wearOS/src/main/java/com/baseio/wearos/ui/theme/Theme.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.wearos.ui.theme
2 |
3 | import androidx.compose.foundation.isSystemInDarkTheme
4 | import androidx.compose.material.MaterialTheme
5 | import androidx.compose.material.darkColors
6 | import androidx.compose.material.lightColors
7 | import androidx.compose.runtime.Composable
8 |
9 | private val DarkColorPalette = darkColors(
10 | primary = Purple200,
11 | primaryVariant = Purple700,
12 | secondary = Teal200
13 | )
14 |
15 | private val LightColorPalette = lightColors(
16 | primary = Purple500,
17 | primaryVariant = Purple700,
18 | secondary = Teal200
19 |
20 | /* Other default colors to override
21 | background = Color.White,
22 | surface = Color.White,
23 | onPrimary = Color.White,
24 | onSecondary = Color.Black,
25 | onBackground = Color.Black,
26 | onSurface = Color.Black,
27 | */
28 | )
29 |
30 | @Composable
31 | fun BaseiOKMMTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
32 | val colors = if (darkTheme) {
33 | DarkColorPalette
34 | } else {
35 | LightColorPalette
36 | }
37 |
38 | MaterialTheme(
39 | colors = colors,
40 | typography = Typography,
41 | shapes = Shapes,
42 | content = content
43 | )
44 | }
--------------------------------------------------------------------------------
/androidApp/src/main/java/com/baseio/kmm/android/ui/theme/Theme.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.android.ui.theme
2 |
3 | import androidx.compose.foundation.isSystemInDarkTheme
4 | import androidx.compose.material.MaterialTheme
5 | import androidx.compose.material.darkColors
6 | import androidx.compose.material.lightColors
7 | import androidx.compose.runtime.Composable
8 |
9 | private val DarkColorPalette = darkColors(
10 | primary = Purple200,
11 | primaryVariant = Purple700,
12 | secondary = Teal200
13 | )
14 |
15 | private val LightColorPalette = lightColors(
16 | primary = Purple500,
17 | primaryVariant = Purple700,
18 | secondary = Teal200
19 |
20 | /* Other default colors to override
21 | background = Color.White,
22 | surface = Color.White,
23 | onPrimary = Color.White,
24 | onSecondary = Color.Black,
25 | onBackground = Color.Black,
26 | onSurface = Color.Black,
27 | */
28 | )
29 |
30 | @Composable
31 | fun BaseiOKMMTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
32 | val colors = if (darkTheme) {
33 | DarkColorPalette
34 | } else {
35 | LightColorPalette
36 | }
37 |
38 | MaterialTheme(
39 | colors = colors,
40 | typography = Typography,
41 | shapes = Shapes,
42 | content = content
43 | )
44 | }
--------------------------------------------------------------------------------
/macOS/macOSTests/macOSTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // macOSTests.swift
3 | // macOSTests
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import XCTest
9 | @testable import macOS
10 |
11 | class macOSTests: XCTestCase {
12 |
13 | override func setUpWithError() throws {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 | }
16 |
17 | override func tearDownWithError() throws {
18 | // Put teardown code here. This method is called after the invocation of each test method in the class.
19 | }
20 |
21 | func testExample() throws {
22 | // This is an example of a functional test case.
23 | // Use XCTAssert and related functions to verify your tests produce the correct results.
24 | // Any test you write for XCTest can be annotated as throws and async.
25 | // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
26 | // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
27 | }
28 |
29 | func testPerformanceExample() throws {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/wearOS/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | WearOSPlugins.plugins.forEach { dependency ->
3 | id(dependency)
4 | }
5 | WearOSPlugins.kotlinPlugins.forEach { dependency ->
6 | kotlin(dependency)
7 | }
8 | }
9 |
10 | android {
11 | compileSdk = 31
12 | defaultConfig {
13 | applicationId = "com.baseio.wearos"
14 | minSdk = 30
15 | targetSdk = 31
16 | versionCode = 1
17 | versionName = "1.0"
18 | vectorDrawables {
19 | useSupportLibrary = true
20 | }
21 | }
22 |
23 | buildTypes {
24 | getByName("release") {
25 | isMinifyEnabled = false
26 | }
27 | }
28 | buildFeatures {
29 | viewBinding = true
30 | compose = true
31 | }
32 | compileOptions {
33 | sourceCompatibility = JavaVersion.VERSION_1_8
34 | targetCompatibility = JavaVersion.VERSION_1_8
35 | }
36 | kotlinOptions {
37 | jvmTarget = "1.8"
38 | }
39 | composeOptions {
40 | kotlinCompilerExtensionVersion = AndroidDependencyVersions.composeKotlinCompiler
41 | }
42 | packagingOptions {
43 | resources {
44 | excludes += "/META-INF/{AL2.0,LGPL2.1}"
45 | }
46 | }
47 | }
48 |
49 | dependencies {
50 | implementation(project(":shared"))
51 | WearOSDependencies.implementation.forEach(::implementation)
52 | }
53 |
--------------------------------------------------------------------------------
/watchApp/watchAppTests/watchAppTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // watchAppTests.swift
3 | // watchAppTests
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import XCTest
9 | @testable import watchApp_WatchKit_Extension
10 |
11 | class watchAppTests: XCTestCase {
12 |
13 | override func setUpWithError() throws {
14 | // Put setup code here. This method is called before the invocation of each test method in the class.
15 | }
16 |
17 | override func tearDownWithError() throws {
18 | // Put teardown code here. This method is called after the invocation of each test method in the class.
19 | }
20 |
21 | func testExample() throws {
22 | // This is an example of a functional test case.
23 | // Use XCTAssert and related functions to verify your tests produce the correct results.
24 | // Any test you write for XCTest can be annotated as throws and async.
25 | // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
26 | // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
27 | }
28 |
29 | func testPerformanceExample() throws {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/Assets.xcassets/Complication.complicationset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "assets" : [
3 | {
4 | "filename" : "Circular.imageset",
5 | "idiom" : "watch",
6 | "role" : "circular"
7 | },
8 | {
9 | "filename" : "Extra Large.imageset",
10 | "idiom" : "watch",
11 | "role" : "extra-large"
12 | },
13 | {
14 | "filename" : "Graphic Bezel.imageset",
15 | "idiom" : "watch",
16 | "role" : "graphic-bezel"
17 | },
18 | {
19 | "filename" : "Graphic Circular.imageset",
20 | "idiom" : "watch",
21 | "role" : "graphic-circular"
22 | },
23 | {
24 | "filename" : "Graphic Corner.imageset",
25 | "idiom" : "watch",
26 | "role" : "graphic-corner"
27 | },
28 | {
29 | "filename" : "Graphic Extra Large.imageset",
30 | "idiom" : "watch",
31 | "role" : "graphic-extra-large"
32 | },
33 | {
34 | "filename" : "Graphic Large Rectangular.imageset",
35 | "idiom" : "watch",
36 | "role" : "graphic-large-rectangular"
37 | },
38 | {
39 | "filename" : "Modular.imageset",
40 | "idiom" : "watch",
41 | "role" : "modular"
42 | },
43 | {
44 | "filename" : "Utilitarian.imageset",
45 | "idiom" : "watch",
46 | "role" : "utilitarian"
47 | }
48 | ],
49 | "info" : {
50 | "author" : "xcode",
51 | "version" : 1
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/iosApp/iosApp/githubtrending/GithubTrendingUI.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import shared
3 |
4 |
5 | struct GithubTrendingScreen: View {
6 |
7 | @ObservedObject var ghVM = GithubTrendingVM()
8 | @State private var searchText = ""
9 |
10 | var body: some View {
11 | NavigationView{
12 | List{
13 | ForEach(ghVM.repos){ repo in
14 | RepoItem(repo:repo)
15 | }
16 | }.refreshable {
17 | ghVM.refresh()
18 | }.onAppear{
19 | ghVM.activate()
20 | }.onDisappear(){
21 | ghVM.destroy()
22 | }.navigationTitle("Trending Repos")
23 | }
24 | }
25 | }
26 |
27 | struct RepoItem : View{
28 |
29 | let repo : UIRepo
30 | @Environment(\.openURL) var openURL
31 |
32 | var body: some View{
33 | HStack{
34 | VStack{
35 | Text(repo.name ?? "NA").fontWeight(.bold).frame(maxWidth:.infinity,alignment: Alignment.topLeading)
36 | Text(repo.author ?? "NA").frame(maxWidth:.infinity,alignment: Alignment.topLeading)
37 | Button {
38 | openURL(URL(string: repo.url ?? "no url")!)
39 | } label: {
40 | Text(repo.url ?? "no url").frame(maxWidth:.infinity,alignment: Alignment.topLeading)
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/iosApp/iosApp/githubtrending/GithubTrendingVM.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GithubTrendingVM.swift
3 | // iosApp
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | // Copyright © 2021 orgName. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import shared
11 | import Combine
12 | import KMPNativeCoroutinesCombine
13 |
14 | class GithubTrendingVM : ObservableObject{
15 | private var trendingDataModel:GithubTrendingDataModel?
16 |
17 | @Published var repos : [UIRepo] = []
18 | @Published
19 | var loading = false
20 | @Published
21 | var error: String?
22 |
23 | func activate(){
24 | trendingDataModel = GithubTrendingDataModel { [weak self] dataState in
25 | self?.loading = dataState is GithubTrendingDataModel.LoadingState
26 | if(dataState is GithubTrendingDataModel.SuccessState){
27 | let listDataState = dataState as! GithubTrendingDataModel.SuccessState
28 | self?.repos = listDataState.trendingList.map({ item in
29 | return UIRepo(author:item.author, name:item.name, avatar:item.avatar, url:item.url)
30 | })
31 | }
32 | }
33 | trendingDataModel?.activate()
34 | }
35 |
36 | func filter(searchText:String){
37 | trendingDataModel?.filterRecords(search:searchText)
38 | }
39 |
40 | func destroy(){
41 | trendingDataModel?.destroy()
42 | }
43 |
44 | func refresh(){
45 | trendingDataModel?.refresh()
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/data/local/GithubTrendingLocalImpl.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.data.local
2 |
3 | import com.baseio.kmm.db.BaseIoDB
4 | import com.baseio.kmm.db.asFlow
5 | import com.baseio.kmm.db.mapToList
6 | import com.baseio.kmm.domain.model.GithubReposItem
7 | import com.squareup.sqldelight.db.SqlDriver
8 | import db.Trending_repos
9 | import kotlinx.coroutines.flow.Flow
10 | import kotlinx.coroutines.flow.asFlow
11 |
12 | class GithubTrendingLocalImpl(override var driver: SqlDriver? = null) : GithubTrendingLocal {
13 | private val database by lazy { BaseIoDB(driver!!) }
14 | private val dbQuery by lazy { database.baseIoDBQueries }
15 |
16 | fun clearDatabase() {
17 | dbQuery.transaction {
18 | dbQuery.deleteAllRepos()
19 | }
20 | }
21 |
22 | override fun getAll(): Flow> {
23 | return dbQuery.selectAllRepos().asFlow().mapToList()
24 | }
25 |
26 | override fun saveRepos(input: List) {
27 | dbQuery.transaction {
28 | dbQuery.deleteAllRepos()
29 | input.forEach {
30 | dbQuery.insertRepo(
31 | uid = it.author + it.url,
32 | author = it.author,
33 | avatar = it.avatar,
34 | description = it.description,
35 | language = it.language,
36 | name = it.name,
37 | url = it.url
38 | )
39 | }
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/wearOS/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
34 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/macOS/macOS/githubtrending/GithubTrendingUI.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import shared
3 |
4 |
5 | struct GithubTrendingScreen: View {
6 |
7 | @ObservedObject var ghVM = GithubTrendingVM()
8 | @State private var searchText = ""
9 |
10 | var body: some View {
11 | NavigationView{
12 | List{
13 | ForEach(ghVM.repos){ repo in
14 | RepoItem(repo:repo)
15 | }
16 | }.refreshable {
17 | ghVM.refresh()
18 | }.onAppear{
19 | ghVM.activate()
20 | }.onDisappear(){
21 | ghVM.destroy()
22 | }.navigationTitle("Trending Repos")
23 | }.searchable(text: $searchText,prompt: "Search by language.").onChange(of: searchText) { searchText in
24 | self.ghVM.filter(searchText:searchText)
25 | }
26 | }
27 | }
28 |
29 | struct RepoItem : View{
30 |
31 | let repo : UIRepo
32 | @Environment(\.openURL) var openURL
33 |
34 | var body: some View{
35 | HStack{
36 | VStack{
37 | Text(repo.name ?? "NA").fontWeight(.bold).frame(maxWidth:.infinity,alignment: Alignment.topLeading)
38 | Text(repo.author ?? "NA").frame(maxWidth:.infinity,alignment: Alignment.topLeading)
39 | Button {
40 | openURL(URL(string: repo.url ?? "no url")!)
41 | } label: {
42 | Text(repo.url ?? "no url").frame(maxWidth:.infinity,alignment: Alignment.topLeading)
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/macOS/macOS/githubtrending/GithubTrendingVM.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GithubTrendingVM.swift
3 | // iosApp
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | // Copyright © 2021 orgName. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import shared
11 | import Combine
12 | import KMPNativeCoroutinesCombine
13 |
14 | class GithubTrendingVM : ObservableObject{
15 | private var trendingDataModel:GithubTrendingDataModel?
16 |
17 | @Published var repos : [UIRepo] = []
18 | @Published
19 | var loading = false
20 | @Published
21 | var error: String?
22 |
23 | init() {
24 | activate()
25 | }
26 |
27 | func activate(){
28 | trendingDataModel = GithubTrendingDataModel { [weak self] dataState in
29 | self?.loading = dataState is GithubTrendingDataModel.LoadingState
30 | if(dataState is GithubTrendingDataModel.SuccessState){
31 | let listDataState = dataState as! GithubTrendingDataModel.SuccessState
32 | self?.repos = listDataState.trendingList.map({ item in
33 | return UIRepo(author:item.author, name:item.name, avatar:item.avatar, url:item.url)
34 | })
35 | }
36 | }
37 | trendingDataModel?.activate()
38 | }
39 |
40 | func filter(searchText:String){
41 | trendingDataModel?.filterRecords(search:searchText)
42 | }
43 |
44 |
45 | func destroy(){
46 | trendingDataModel?.destroy()
47 | }
48 |
49 | func refresh(){
50 | trendingDataModel?.refresh()
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/macOS/macOSUITests/macOSUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // macOSUITests.swift
3 | // macOSUITests
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import XCTest
9 |
10 | class macOSUITests: XCTestCase {
11 |
12 | override func setUpWithError() throws {
13 | // Put setup code here. This method is called before the invocation of each test method in the class.
14 |
15 | // In UI tests it is usually best to stop immediately when a failure occurs.
16 | continueAfterFailure = false
17 |
18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
19 | }
20 |
21 | override func tearDownWithError() throws {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | }
24 |
25 | func testExample() throws {
26 | // UI tests must launch the application that they test.
27 | let app = XCUIApplication()
28 | app.launch()
29 |
30 | // Use recording to get started writing UI tests.
31 | // Use XCTAssert and related functions to verify your tests produce the correct results.
32 | }
33 |
34 | func testLaunchPerformance() throws {
35 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
36 | // This measures how long it takes to launch your application.
37 | measure(metrics: [XCTApplicationLaunchMetric()]) {
38 | XCUIApplication().launch()
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/githubtrending/GithubTrendingVM.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GithubTrendingVM.swift
3 | // iosApp
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | // Copyright © 2021 orgName. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import shared
11 | import Combine
12 | import KMPNativeCoroutinesCombine
13 |
14 | class GithubTrendingVM : ObservableObject{
15 | private var trendingDataModel:GithubTrendingDataModel?
16 |
17 | @Published var repos : [UIRepo] = []
18 | @Published
19 | var loading = false
20 | @Published
21 | var error: String?
22 |
23 | init() {
24 | activate()
25 | }
26 |
27 | func activate(){
28 | trendingDataModel = GithubTrendingDataModel { [weak self] dataState in
29 | self?.loading = dataState is GithubTrendingDataModel.LoadingState
30 | if(dataState is GithubTrendingDataModel.SuccessState){
31 | let listDataState = dataState as! GithubTrendingDataModel.SuccessState
32 | self?.repos = listDataState.trendingList.map({ item in
33 | return UIRepo(author:item.author, name:item.name, avatar:item.avatar, url:item.url)
34 | })
35 | }
36 | }
37 | trendingDataModel?.activate()
38 | }
39 |
40 | func filter(searchText:String){
41 | trendingDataModel?.filterRecords(search:searchText)
42 | }
43 |
44 |
45 | func destroy(){
46 | trendingDataModel?.destroy()
47 | }
48 |
49 | func refresh(){
50 | trendingDataModel?.refresh()
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/androidApp/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | AndroidPluginDependencies.plugins.forEach { (lib, v) ->
3 | if (v.isNotBlank()) {
4 | id(lib) version v
5 | } else {
6 | id(lib)
7 | }
8 | }
9 | }
10 |
11 | android {
12 | compileSdk = 31
13 | defaultConfig {
14 | applicationId = "com.baseio.kmm.android"
15 | minSdk = 21
16 | targetSdk = 31
17 | versionCode = 1
18 | versionName = "1.0"
19 | vectorDrawables {
20 | useSupportLibrary = true
21 | }
22 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
23 | }
24 | buildTypes {
25 | getByName("release") {
26 | isMinifyEnabled = false
27 | }
28 | }
29 | compileOptions {
30 | sourceCompatibility = JavaVersion.VERSION_1_8
31 | targetCompatibility = JavaVersion.VERSION_1_8
32 | }
33 | kotlinOptions {
34 | jvmTarget = "1.8"
35 | }
36 | buildFeatures {
37 | compose = true
38 | }
39 | composeOptions {
40 | kotlinCompilerExtensionVersion = AndroidDependencyVersions.composeKotlinCompiler
41 | }
42 | packagingOptions {
43 | resources {
44 | excludes += "/META-INF/{AL2.0,LGPL2.1}"
45 | }
46 | }
47 | }
48 |
49 | dependencies {
50 | implementation(project(":shared"))
51 | AndroidDependencies.implementation.forEach(::implementation)
52 | AndroidDependencies.androidTestImplementation.forEach(::androidTestImplementation)
53 | AndroidDependencies.debugImplementation.forEach(::debugImplementation)
54 | }
55 |
--------------------------------------------------------------------------------
/watchApp/watchAppUITests/watchAppUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // watchAppUITests.swift
3 | // watchAppUITests
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import XCTest
9 |
10 | class watchAppUITests: XCTestCase {
11 |
12 | override func setUpWithError() throws {
13 | // Put setup code here. This method is called before the invocation of each test method in the class.
14 |
15 | // In UI tests it is usually best to stop immediately when a failure occurs.
16 | continueAfterFailure = false
17 |
18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
19 | }
20 |
21 | override func tearDownWithError() throws {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | }
24 |
25 | func testExample() throws {
26 | // UI tests must launch the application that they test.
27 | let app = XCUIApplication()
28 | app.launch()
29 |
30 | // Use recording to get started writing UI tests.
31 | // Use XCTAssert and related functions to verify your tests produce the correct results.
32 | }
33 |
34 | func testLaunchPerformance() throws {
35 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
36 | // This measures how long it takes to launch your application.
37 | measure(metrics: [XCTApplicationLaunchMetric()]) {
38 | XCUIApplication().launch()
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/iosApp/iosApp/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // iosApp
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | // Copyright © 2021 orgName. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | import UIKit
12 | import shared
13 |
14 |
15 | let sharedComponent = SharedComponent()
16 | let useCasesComponent = UseCasesComponent()
17 |
18 | class AppDelegate: UIResponder, UIApplicationDelegate {
19 |
20 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
21 |
22 | KoinKt.doInitSharedDependencies()
23 |
24 | return true
25 | }
26 |
27 | // MARK: UISceneSession Lifecycle
28 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
29 | // Called when a new scene session is being created.
30 | // Use this method to select a configuration to create the new scene with.
31 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
32 | }
33 |
34 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
35 | // Called when the user discards a scene session.
36 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
37 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/githubtrending/GithubTrendingUI.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import shared
3 | import SDWebImageSwiftUI
4 |
5 |
6 | struct GithubTrendingScreen: View {
7 |
8 | @ObservedObject var ghVM = GithubTrendingVM()
9 | @State private var searchText = ""
10 |
11 | var body: some View {
12 | NavigationView{
13 | List{
14 | ForEach(ghVM.repos){ repo in
15 | RepoItem(repo:repo)
16 | }
17 | }.refreshable {
18 | ghVM.refresh()
19 | }.onAppear{
20 | ghVM.activate()
21 | }.onDisappear(){
22 | ghVM.destroy()
23 | }.navigationTitle("Trending Repos")
24 | }.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always),prompt: "Search by language.").onChange(of: searchText) { searchText in
25 | self.ghVM.filter(searchText:searchText)
26 | }
27 | }
28 | }
29 |
30 | struct RepoItem : View{
31 |
32 | let repo : UIRepo
33 | @Environment(\.openURL) var openURL
34 |
35 | var body: some View{
36 | HStack{
37 | VStack{
38 | Text(repo.name ?? "NA").fontWeight(.bold).frame(maxWidth:.infinity,alignment: Alignment.topLeading)
39 | Text(repo.author ?? "NA").frame(maxWidth:.infinity,alignment: Alignment.topLeading)
40 | Button {
41 | openURL(URL(string: repo.url ?? "no url")!)
42 | } label: {
43 | Text(repo.url ?? "no url").frame(maxWidth:.infinity,alignment: Alignment.topLeading)
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/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 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 |
28 | UIRequiredDeviceCapabilities
29 |
30 | armv7
31 |
32 | UISupportedInterfaceOrientations
33 |
34 | UIInterfaceOrientationPortrait
35 | UIInterfaceOrientationLandscapeLeft
36 | UIInterfaceOrientationLandscapeRight
37 |
38 | UISupportedInterfaceOrientations~ipad
39 |
40 | UIInterfaceOrientationPortrait
41 | UIInterfaceOrientationPortraitUpsideDown
42 | UIInterfaceOrientationLandscapeLeft
43 | UIInterfaceOrientationLandscapeRight
44 |
45 | UILaunchScreen
46 |
47 |
48 |
--------------------------------------------------------------------------------
/shared/shared.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = 'shared'
3 | spec.version = '1.0'
4 | spec.homepage = 'Link to the Shared Module homepage'
5 | spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
6 | spec.authors = ''
7 | spec.license = ''
8 | spec.summary = 'Some description for the Shared Module'
9 |
10 | spec.vendored_frameworks = "build/cocoapods/framework/shared.framework"
11 | spec.libraries = "c++"
12 | spec.module_name = "#{spec.name}_umbrella"
13 |
14 | spec.ios.deployment_target = '14.1'
15 |
16 |
17 |
18 | spec.pod_target_xcconfig = {
19 | 'KOTLIN_PROJECT_PATH' => ':shared',
20 | 'PRODUCT_MODULE_NAME' => 'shared',
21 | }
22 |
23 | spec.script_phases = [
24 | {
25 | :name => 'Build shared',
26 | :execution_position => :before_compile,
27 | :shell_path => '/bin/sh',
28 | :script => <<-SCRIPT
29 | if [ "YES" = "$COCOAPODS_SKIP_KOTLIN_BUILD" ]; then
30 | echo "Skipping Gradle build task invocation due to COCOAPODS_SKIP_KOTLIN_BUILD environment variable set to \"YES\""
31 | exit 0
32 | fi
33 | set -ev
34 | REPO_ROOT="$PODS_TARGET_SRCROOT"
35 | "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \
36 | -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \
37 | -Pkotlin.native.cocoapods.archs="$ARCHS" \
38 | -Pkotlin.native.cocoapods.configuration=$CONFIGURATION
39 | SCRIPT
40 | }
41 | ]
42 | end
--------------------------------------------------------------------------------
/compose-desktop/src/jvmMain/kotlin/TrendingReposListScreen.kt:
--------------------------------------------------------------------------------
1 | import androidx.compose.animation.AnimatedVisibility
2 | import androidx.compose.foundation.Image
3 | import androidx.compose.foundation.layout.*
4 | import androidx.compose.foundation.lazy.LazyColumn
5 | import androidx.compose.material.CircularProgressIndicator
6 | import androidx.compose.material.Text
7 | import androidx.compose.runtime.Composable
8 | import androidx.compose.runtime.collectAsState
9 | import androidx.compose.runtime.getValue
10 | import androidx.compose.runtime.remember
11 | import androidx.compose.ui.Modifier
12 | import androidx.compose.ui.text.TextStyle
13 | import androidx.compose.ui.text.font.FontWeight
14 | import androidx.compose.ui.unit.dp
15 | import com.baseio.kmm.features.trending.GithubTrendingDataModel
16 |
17 | @Composable
18 | fun TrendingReposListScreen(viewModel: TrendingReposVM) {
19 | Column {
20 | val uiState by remember { viewModel.uiState }
21 | if (uiState is GithubTrendingDataModel.LoadingState) {
22 | CircularProgressIndicator()
23 | }
24 |
25 | AnimatedVisibility(visible = uiState is GithubTrendingDataModel.ErrorState) {
26 | Text(text = (uiState as GithubTrendingDataModel.ErrorState).throwable.message ?:"Error", modifier = Modifier.padding(4.dp))
27 | }
28 |
29 | if(uiState is GithubTrendingDataModel.SuccessState){
30 | LazyColumn {
31 | (uiState as GithubTrendingDataModel.SuccessState).trendingList.forEach {
32 | item {
33 | Row(modifier = Modifier
34 | .fillMaxWidth()
35 | .padding(4.dp)) {
36 |
37 | Column(modifier = Modifier.padding(all = 8.dp)) {
38 | Text(text = it.author ?: "author", style = TextStyle(fontWeight = FontWeight.Bold))
39 | Text(text = it.name ?: "name")
40 | }
41 | }
42 | }
43 | }
44 | item {
45 | Spacer(modifier = Modifier)
46 | }
47 | }
48 | }
49 |
50 |
51 | }
52 | }
--------------------------------------------------------------------------------
/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PraxisKMM
2 |
3 | Minimal **Kotlin Multiplatform** project with SwiftUI, Jetpack Compose, Compose for Wear OS,. Currently running on
4 |
5 | * Desktop JVM (Jetpack Compose) ✅ DONE
6 | * Android (Jetpack Compose) ✅ DONE
7 | * Android App Widget 🚧 TODO
8 | * Wear OS (Compose for Wear OS) ✅ DONE
9 | * iOS (SwiftUI) ✅ DONE
10 | * iOS App Widget (SwiftUI) 🚧 TODO
11 | * watchOS (SwiftUI) ✅ DONE
12 | * macOS (SwiftUI) ✅ DONE
13 | * Web (ReactJS) ✅ DONE
14 |
15 | ### TODOs
16 |
17 | 1. Koin does not allow to return dependencies with await() which affects providing SqlDriver on JSPlatform.
18 | Figure out a way for proper DI for SQlDriver.
19 | see issue here: https://github.com/InsertKoinIO/koin/issues/388
20 |
21 | ### Screenshots
22 |
23 | * Compose Desktop (Compose for Desktop)
24 |
25 |
26 |
27 | * Android Wear OS (Compose for Wear OS)
28 |
29 |
30 |
31 | * Android (Jetpack Compose)
32 |
33 |
34 |
35 | * watchOS (SwiftUI)
36 |
37 |
38 |
39 | * iOS (SwiftUI)
40 |
41 |
42 |
43 | * macOS (SwiftUI)
44 |
45 |
46 |
47 | * Web (ReactJS)
48 |
49 |
50 |
51 | ### Languages, libraries and tools used
52 |
53 | * [Kotlin](https://kotlinlang.org/)
54 | * [Kotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)
55 | * [Kotlinx Serialization](https://github.com/Kotlin/kotlinx.serialization)
56 | * [Ktor client library](https://github.com/ktorio/ktor)
57 | * [Android Architecture Components](https://developer.android.com/topic/libraries/architecture/index.html)
58 | * [Koin](https://github.com/InsertKoinIO/koin)
59 | * [SQLDelight](https://github.com/cashapp/sqldelight)
60 | * [Jetpack Compose](https://developer.android.com/jetpack/compose)
61 | * [SwiftUI](https://developer.apple.com/documentation/swiftui)
62 | * [KMP-NativeCoroutines](https://github.com/rickclephas/KMP-NativeCoroutines)
--------------------------------------------------------------------------------
/wearOS/src/main/java/com/baseio/wearos/TrendingReposVM.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.wearos
2 |
3 | import android.app.Application
4 | import androidx.compose.runtime.getValue
5 | import androidx.compose.runtime.mutableStateOf
6 | import androidx.compose.runtime.setValue
7 | import androidx.lifecycle.AndroidViewModel
8 | import androidx.lifecycle.ViewModel
9 | import androidx.lifecycle.viewModelScope
10 | import com.baseio.kmm.db.DriverFactory
11 | import com.baseio.kmm.domain.model.GithubReposItem
12 | import com.squareup.sqldelight.db.SqlDriver
13 | import kotlinx.coroutines.Dispatchers
14 | import kotlinx.coroutines.delay
15 | import kotlinx.coroutines.flow.collectLatest
16 | import kotlinx.coroutines.launch
17 | import kotlinx.coroutines.withContext
18 |
19 | class TrendingReposVM(app: Application) : AndroidViewModel(app) {
20 | var uiState by mutableStateOf(TrendingReposUiState(emptyList(), true, message = "Loading..."))
21 | private set
22 |
23 | init {
24 | listenToChanges()
25 | fetchData()
26 | }
27 |
28 | private fun fetchData() {
29 | viewModelScope.launch {
30 | withContext(Dispatchers.IO) {
31 | try {
32 | val data = useCasesComponent.provideFetchTrendingReposUseCase().perform("Kotlin")
33 | precheckSqlite()
34 | useCasesComponent.provideSaveTrendingReposUseCase().perform(data)
35 | } catch (ex: Exception) {
36 | ex.printStackTrace()
37 | uiState = uiState.copy(message = ex.message ?: "Error")
38 | }
39 | }
40 | }
41 | }
42 |
43 | private fun listenToChanges() {
44 | viewModelScope.launch {
45 | precheckSqlite()
46 | useCasesComponent.provideGetLocalReposUseCase().perform(null).collectLatest {
47 | uiState = TrendingReposUiState(it, false, "")
48 | uiState = uiState.copy(dataToDisplayOnScreen = it, loading = false)
49 | }
50 | }
51 | }
52 |
53 | private suspend fun precheckSqlite() {
54 | if (sharedComponent.provideGithubTrendingLocal().driver == null) {
55 | val driver = DriverFactory(context = getApplication()).createDriverBlocking()
56 | sharedComponent.provideGithubTrendingLocal().driver = driver
57 | }
58 | }
59 | }
60 |
61 |
62 | data class TrendingReposUiState(
63 | val dataToDisplayOnScreen: List = emptyList(),
64 | val loading: Boolean = false,
65 | val message: String = ""
66 | )
67 |
--------------------------------------------------------------------------------
/wearOS/src/main/java/com/baseio/wearos/TrendingReposListScreen.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.wearos
2 |
3 | import androidx.compose.foundation.Image
4 | import androidx.compose.foundation.layout.*
5 | import androidx.compose.foundation.lazy.LazyColumn
6 | import androidx.compose.material.CircularProgressIndicator
7 | import androidx.compose.material.Text
8 | import androidx.compose.runtime.Composable
9 | import androidx.compose.runtime.remember
10 | import androidx.compose.ui.Modifier
11 | import androidx.compose.ui.platform.LocalConfiguration
12 | import androidx.compose.ui.text.TextStyle
13 | import androidx.compose.ui.text.font.FontWeight
14 | import androidx.compose.ui.unit.dp
15 | import coil.compose.rememberImagePainter
16 |
17 | @Composable
18 | fun TrendingReposListScreen(viewModel: TrendingReposVM) {
19 | Column {
20 | val configuration = LocalConfiguration.current
21 |
22 | val extraBottomPadding = remember {
23 | if (configuration.isScreenRound) 40.dp else 0.dp
24 | }
25 | val uiState = viewModel.uiState
26 |
27 | if (uiState.loading) {
28 | CircularProgressIndicator()
29 | }
30 |
31 | Text(text = uiState.message, modifier = Modifier.padding(4.dp))
32 |
33 | LazyColumn(
34 | modifier = Modifier
35 | .padding(horizontal = 4.dp),
36 | contentPadding = PaddingValues(
37 | start = 8.dp,
38 | top = 8.dp,
39 | end = 8.dp,
40 | bottom = 8.dp + extraBottomPadding
41 | ),
42 | ) {
43 | uiState.dataToDisplayOnScreen.forEach {
44 | item {
45 | Row(modifier = Modifier.padding(4.dp)) {
46 | Image(
47 | painter = rememberImagePainter(it.avatar),
48 | contentDescription = null,
49 | modifier = Modifier.size(64.dp)
50 | )
51 | Column(modifier = Modifier.padding(all = 8.dp)) {
52 | Text(
53 | text = it.author ?: "author",
54 | style = TextStyle(fontWeight = FontWeight.Bold)
55 | )
56 | Text(text = it.name ?: "name")
57 | }
58 | }
59 | }
60 | }
61 |
62 | }
63 |
64 | }
65 | }
--------------------------------------------------------------------------------
/androidApp/src/main/java/com/baseio/kmm/android/TrendingReposListScreen.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.android
2 |
3 | import androidx.compose.animation.AnimatedVisibility
4 | import androidx.compose.foundation.Image
5 | import androidx.compose.foundation.layout.Column
6 | import androidx.compose.foundation.layout.Row
7 | import androidx.compose.foundation.layout.Spacer
8 | import androidx.compose.foundation.layout.fillMaxWidth
9 | import androidx.compose.foundation.layout.padding
10 | import androidx.compose.foundation.layout.size
11 | import androidx.compose.foundation.lazy.LazyColumn
12 | import androidx.compose.material.CircularProgressIndicator
13 | import androidx.compose.material.Text
14 | import androidx.compose.runtime.*
15 | import androidx.compose.ui.Modifier
16 | import androidx.compose.ui.text.TextStyle
17 | import androidx.compose.ui.text.font.FontWeight
18 | import androidx.compose.ui.unit.dp
19 | import coil.compose.rememberImagePainter
20 | import com.baseio.kmm.features.trending.GithubTrendingDataModel
21 | import com.google.accompanist.insets.navigationBarsPadding
22 |
23 | @Composable
24 | fun TrendingReposListScreen(viewModel: TrendingReposVM) {
25 | Column {
26 | val uiState by viewModel.uiState.collectAsState()
27 | if (uiState is GithubTrendingDataModel.LoadingState) {
28 | CircularProgressIndicator()
29 | }
30 |
31 | AnimatedVisibility(visible = uiState is GithubTrendingDataModel.ErrorState) {
32 | Text(text = (uiState as GithubTrendingDataModel.ErrorState).throwable.message ?:"Error", modifier = Modifier.padding(4.dp))
33 | }
34 |
35 | if(uiState is GithubTrendingDataModel.SuccessState){
36 | LazyColumn {
37 | (uiState as GithubTrendingDataModel.SuccessState).trendingList.forEach {
38 | item {
39 | Row(modifier = Modifier
40 | .fillMaxWidth()
41 | .padding(4.dp)) {
42 | Image(
43 | painter = rememberImagePainter(it.avatar),
44 | contentDescription = null,
45 | modifier = Modifier.size(64.dp)
46 | )
47 | Column(modifier = Modifier.padding(all = 8.dp)) {
48 | Text(text = it.author ?: "author", style = TextStyle(fontWeight = FontWeight.Bold))
49 | Text(text = it.name ?: "name")
50 | }
51 | }
52 | }
53 | }
54 | item {
55 | Spacer(modifier = Modifier.navigationBarsPadding())
56 | }
57 | }
58 | }
59 |
60 |
61 | }
62 | }
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit Extension/ComplicationController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ComplicationController.swift
3 | // watchApp WatchKit Extension
4 | //
5 | // Created by Anmol Verma on 27/12/21.
6 | //
7 |
8 | import ClockKit
9 |
10 |
11 | class ComplicationController: NSObject, CLKComplicationDataSource {
12 |
13 | // MARK: - Complication Configuration
14 |
15 | func getComplicationDescriptors(handler: @escaping ([CLKComplicationDescriptor]) -> Void) {
16 | let descriptors = [
17 | CLKComplicationDescriptor(identifier: "complication", displayName: "watchApp", supportedFamilies: CLKComplicationFamily.allCases)
18 | // Multiple complication support can be added here with more descriptors
19 | ]
20 |
21 | // Call the handler with the currently supported complication descriptors
22 | handler(descriptors)
23 | }
24 |
25 | func handleSharedComplicationDescriptors(_ complicationDescriptors: [CLKComplicationDescriptor]) {
26 | // Do any necessary work to support these newly shared complication descriptors
27 | }
28 |
29 | // MARK: - Timeline Configuration
30 |
31 | func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
32 | // Call the handler with the last entry date you can currently provide or nil if you can't support future timelines
33 | handler(nil)
34 | }
35 |
36 | func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) {
37 | // Call the handler with your desired behavior when the device is locked
38 | handler(.showOnLockScreen)
39 | }
40 |
41 | // MARK: - Timeline Population
42 |
43 | func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
44 | // Call the handler with the current timeline entry
45 | handler(nil)
46 | }
47 |
48 | func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
49 | // Call the handler with the timeline entries after the given date
50 | handler(nil)
51 | }
52 |
53 | // MARK: - Sample Templates
54 |
55 | func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
56 | // This method will be called once per supported complication, and the results will be cached
57 | handler(nil)
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/features/trending/GithubTrendingDataModel.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.features.trending
2 |
3 | import com.baseio.kmm.di.UseCasesComponent
4 | import com.baseio.kmm.domain.model.GithubReposItem
5 | import com.baseio.kmm.datamodel.PraxisDataModel
6 | import kotlinx.coroutines.CoroutineExceptionHandler
7 | import kotlinx.coroutines.Job
8 | import kotlinx.coroutines.cancel
9 | import kotlinx.coroutines.flow.MutableStateFlow
10 | import kotlinx.coroutines.flow.collectLatest
11 | import kotlinx.coroutines.launch
12 | import org.koin.core.component.KoinComponent
13 |
14 | class GithubTrendingDataModel(
15 | private val onDataState: (DataState) -> Unit
16 | ) : PraxisDataModel(), KoinComponent {
17 |
18 | private var currentLoadingJob: Job? = null
19 | private val useCasesComponent = UseCasesComponent()
20 |
21 | private val _trendingStateFlow: MutableStateFlow = MutableStateFlow(EmptyState)
22 |
23 | private val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
24 | _trendingStateFlow.value = ErrorState(throwable)
25 | }
26 |
27 | override fun activate() {
28 | listenState()
29 | readLocalRepositories()
30 | fetchTrendingRepos()
31 | }
32 |
33 | override fun destroy() {
34 | dataModelScope.cancel()
35 | }
36 |
37 | override fun refresh() {
38 | fetchTrendingRepos()
39 | }
40 |
41 |
42 | private fun listenState() {
43 | dataModelScope.launch {
44 | _trendingStateFlow.collectLatest {
45 | onDataState(it)
46 | }
47 | }
48 | }
49 |
50 | private fun readLocalRepositories() {
51 | dataModelScope.launch(exceptionHandler) {
52 | useCasesComponent.provideGetLocalReposUseCase().perform(input = null).collectLatest { list ->
53 | _trendingStateFlow.value = SuccessState(list)
54 | }
55 | }
56 | }
57 |
58 | fun filterRecords(search: String? = null) {
59 | fetchTrendingRepos(search)
60 | }
61 |
62 | private fun fetchTrendingRepos(search: String? = "kotlin") {
63 | currentLoadingJob?.cancel()
64 | currentLoadingJob = dataModelScope.launch(exceptionHandler) {
65 | _trendingStateFlow.value = LoadingState
66 | val repos = useCasesComponent.provideFetchTrendingReposUseCase().perform(search)
67 | useCasesComponent.provideSaveTrendingReposUseCase().perform(repos)
68 | }
69 |
70 | }
71 |
72 | sealed class DataState
73 | object LoadingState : DataState()
74 | object EmptyState : DataState()
75 | object Complete : DataState()
76 | data class SuccessState(
77 | val trendingList: List,
78 | ) : DataState()
79 |
80 | data class ErrorState(var throwable: Throwable) : DataState()
81 | }
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/di/Koin.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.di
2 |
3 | import com.baseio.kmm.data.local.GithubTrendingLocal
4 | import com.baseio.kmm.data.local.GithubTrendingLocalImpl
5 | import com.baseio.kmm.data.network.GithubTrendingAPI
6 | import com.baseio.kmm.data.network.GithubTrendingAPIImpl
7 | import com.baseio.kmm.domain.usecases.trendingrepos.FetchTrendingReposUseCase
8 | import com.baseio.kmm.domain.usecases.trendingrepos.GetLocalReposUseCase
9 | import com.baseio.kmm.domain.usecases.trendingrepos.SaveTrendingReposUseCase
10 | import io.ktor.client.*
11 | import io.ktor.client.engine.*
12 | import io.ktor.client.features.json.*
13 | import io.ktor.client.features.json.serializer.*
14 | import io.ktor.client.features.logging.*
15 | import org.koin.core.component.KoinComponent
16 | import org.koin.core.context.startKoin
17 | import org.koin.core.module.Module
18 | import org.koin.dsl.module
19 | import org.koin.core.component.get
20 |
21 | fun initSharedDependencies() = startKoin {
22 | modules(commonModule, useCaseModule, platformModule())
23 | }
24 |
25 | fun initSqlDelightExperimentalDependencies() = startKoin {
26 | modules(jsModule, useCaseModule, platformModule())
27 | }
28 |
29 | val commonModule = module {
30 | single { httpClient(get()) }
31 | single { GithubTrendingLocalImpl(get()) }
32 | single { GithubTrendingAPIImpl(get()) }
33 | }
34 |
35 | val jsModule = module {
36 | single { httpClient(get()) }
37 | single { GithubTrendingLocalImpl() }
38 | single { GithubTrendingAPIImpl(get()) }
39 | }
40 |
41 | val useCaseModule = module {
42 | single { FetchTrendingReposUseCase(get()) }
43 | single { SaveTrendingReposUseCase(get()) }
44 | single { GetLocalReposUseCase(get()) }
45 | }
46 |
47 | class UseCasesComponent : KoinComponent {
48 | fun provideFetchTrendingReposUseCase(): FetchTrendingReposUseCase = get()
49 | fun provideSaveTrendingReposUseCase(): SaveTrendingReposUseCase = get()
50 | fun provideGetLocalReposUseCase(): GetLocalReposUseCase = get()
51 | }
52 |
53 | class SharedComponent : KoinComponent {
54 | fun provideGithubTrendingAPI(): GithubTrendingAPI = get()
55 | fun provideGithubTrendingLocal(): GithubTrendingLocal = get()
56 | }
57 |
58 | private fun httpClient(httpClientEngine: HttpClientEngine) = HttpClient(httpClientEngine) {
59 | val json = kotlinx.serialization.json.Json { isLenient = true; ignoreUnknownKeys = true }
60 |
61 | install(JsonFeature) {
62 | serializer = KotlinxSerializer(json)
63 | }
64 | install(Logging) {
65 | logger = Logger.DEFAULT
66 | level = LogLevel.ALL
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/watchApp/watchApp WatchKit App/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "watch",
5 | "role" : "notificationCenter",
6 | "scale" : "2x",
7 | "size" : "24x24",
8 | "subtype" : "38mm"
9 | },
10 | {
11 | "idiom" : "watch",
12 | "role" : "notificationCenter",
13 | "scale" : "2x",
14 | "size" : "27.5x27.5",
15 | "subtype" : "42mm"
16 | },
17 | {
18 | "idiom" : "watch",
19 | "role" : "companionSettings",
20 | "scale" : "2x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "watch",
25 | "role" : "companionSettings",
26 | "scale" : "3x",
27 | "size" : "29x29"
28 | },
29 | {
30 | "idiom" : "watch",
31 | "role" : "notificationCenter",
32 | "scale" : "2x",
33 | "size" : "33x33",
34 | "subtype" : "45mm"
35 | },
36 | {
37 | "idiom" : "watch",
38 | "role" : "appLauncher",
39 | "scale" : "2x",
40 | "size" : "40x40",
41 | "subtype" : "38mm"
42 | },
43 | {
44 | "idiom" : "watch",
45 | "role" : "appLauncher",
46 | "scale" : "2x",
47 | "size" : "44x44",
48 | "subtype" : "40mm"
49 | },
50 | {
51 | "idiom" : "watch",
52 | "role" : "appLauncher",
53 | "scale" : "2x",
54 | "size" : "46x46",
55 | "subtype" : "41mm"
56 | },
57 | {
58 | "idiom" : "watch",
59 | "role" : "appLauncher",
60 | "scale" : "2x",
61 | "size" : "50x50",
62 | "subtype" : "44mm"
63 | },
64 | {
65 | "idiom" : "watch",
66 | "role" : "appLauncher",
67 | "scale" : "2x",
68 | "size" : "51x51",
69 | "subtype" : "45mm"
70 | },
71 | {
72 | "idiom" : "watch",
73 | "role" : "quickLook",
74 | "scale" : "2x",
75 | "size" : "86x86",
76 | "subtype" : "38mm"
77 | },
78 | {
79 | "idiom" : "watch",
80 | "role" : "quickLook",
81 | "scale" : "2x",
82 | "size" : "98x98",
83 | "subtype" : "42mm"
84 | },
85 | {
86 | "idiom" : "watch",
87 | "role" : "quickLook",
88 | "scale" : "2x",
89 | "size" : "108x108",
90 | "subtype" : "44mm"
91 | },
92 | {
93 | "idiom" : "watch",
94 | "role" : "quickLook",
95 | "scale" : "2x",
96 | "size" : "117x117",
97 | "subtype" : "45mm"
98 | },
99 | {
100 | "idiom" : "watch-marketing",
101 | "scale" : "1x",
102 | "size" : "1024x1024"
103 | }
104 | ],
105 | "info" : {
106 | "author" : "xcode",
107 | "version" : 1
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/androidApp/src/main/java/com/baseio/kmm/android/TrendingReposUI.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.android
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.compose.setContent
6 | import androidx.compose.foundation.isSystemInDarkTheme
7 | import androidx.compose.foundation.layout.fillMaxSize
8 | import androidx.compose.material.Scaffold
9 | import androidx.compose.material.Surface
10 | import androidx.compose.material.Text
11 | import androidx.compose.material.TopAppBar
12 | import androidx.compose.runtime.Composable
13 | import androidx.compose.runtime.SideEffect
14 | import androidx.compose.ui.Modifier
15 | import androidx.compose.ui.graphics.Color
16 | import androidx.compose.ui.tooling.preview.Preview
17 | import androidx.compose.ui.unit.dp
18 | import androidx.core.view.WindowCompat
19 | import com.baseio.kmm.android.ui.theme.BaseiOKMMTheme
20 | import com.google.accompanist.insets.ProvideWindowInsets
21 | import com.google.accompanist.insets.statusBarsPadding
22 | import com.google.accompanist.systemuicontroller.rememberSystemUiController
23 |
24 | class TrendingReposUI : ComponentActivity() {
25 | override fun onCreate(savedInstanceState: Bundle?) {
26 | super.onCreate(savedInstanceState)
27 | WindowCompat.setDecorFitsSystemWindows(window, false)
28 | val viewModel = TrendingReposVM()
29 | setContent {
30 | BaseiOKMMTheme() {
31 | ProvideWindowInsets {
32 | Surface(
33 | modifier = Modifier
34 | .fillMaxSize()
35 | ) {
36 | val systemUiController = rememberSystemUiController()
37 | val useDarkIcons = isSystemInDarkTheme()
38 |
39 | SideEffect {
40 | systemUiController.setSystemBarsColor(
41 | color = Color.Transparent,
42 | darkIcons = !useDarkIcons
43 | )
44 | }
45 | Scaffold(
46 | topBar = {
47 | Surface(
48 | elevation = 4.dp,
49 | ) {
50 | TopAppBar(
51 | title = { Text(text = "Trending Kotlin Repositories") },
52 | modifier = Modifier.statusBarsPadding(),
53 | )
54 | }
55 | },
56 | content = {
57 | TrendingReposListScreen(viewModel)
58 | },
59 | backgroundColor = Color.Transparent
60 | )
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
68 | @Composable
69 | fun Greeting(name: String) {
70 | Text(text = "Hello $name!")
71 | }
72 |
73 | @Preview(showBackground = true)
74 | @Composable
75 | fun DefaultPreview() {
76 | BaseiOKMMTheme {
77 | Greeting("Android")
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/shared/src/commonMain/kotlin/com/baseio/kmm/db/FlowQuery.kt:
--------------------------------------------------------------------------------
1 | package com.baseio.kmm.db
2 |
3 |
4 | import com.squareup.sqldelight.Query
5 |
6 | /*
7 | * Copyright (C) 2018 Square, Inc.
8 | *
9 | * Licensed under the Apache License, Version 2.0 (the "License");
10 | * you may not use this file except in compliance with the License.
11 | * You may obtain a copy of the License at
12 | *
13 | * http://www.apache.org/licenses/LICENSE-2.0
14 | *
15 | * Unless required by applicable law or agreed to in writing, software
16 | * distributed under the License is distributed on an "AS IS" BASIS,
17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | * See the License for the specific language governing permissions and
19 | * limitations under the License.
20 | */
21 | import kotlinx.coroutines.Dispatchers
22 | import kotlinx.coroutines.channels.Channel
23 | import kotlinx.coroutines.channels.Channel.Factory.CONFLATED
24 | import kotlinx.coroutines.flow.Flow
25 | import kotlinx.coroutines.flow.flow
26 | import kotlinx.coroutines.flow.map
27 | import kotlinx.coroutines.flow.mapNotNull
28 | import kotlinx.coroutines.withContext
29 | import kotlin.coroutines.CoroutineContext
30 | import kotlin.jvm.JvmName
31 | import kotlin.jvm.JvmOverloads
32 |
33 | /** Turns this [Query] into a [Flow] which emits whenever the underlying result set changes. */
34 | @JvmName("toFlow")
35 | fun Query.asFlow(): Flow> = flow {
36 | val channel = Channel(CONFLATED)
37 | channel.trySend(Unit)
38 |
39 | val listener = object : Query.Listener {
40 | override fun queryResultsChanged() {
41 | channel.trySend(Unit)
42 | }
43 | }
44 |
45 | addListener(listener)
46 | try {
47 | for (item in channel) {
48 | emit(this@asFlow)
49 | }
50 | } finally {
51 | removeListener(listener)
52 | }
53 | }
54 |
55 | @JvmOverloads
56 | fun Flow>.mapToOne(
57 | context: CoroutineContext = Dispatchers.Default
58 | ): Flow = map {
59 | withContext(context) {
60 | it.executeAsOne()
61 | }
62 | }
63 |
64 | @JvmOverloads
65 | fun Flow>.mapToOneOrDefault(
66 | defaultValue: T,
67 | context: CoroutineContext = Dispatchers.Default
68 | ): Flow = map {
69 | withContext(context) {
70 | it.executeAsOneOrNull() ?: defaultValue
71 | }
72 | }
73 |
74 | @JvmOverloads
75 | fun Flow>.mapToOneOrNull(
76 | context: CoroutineContext = Dispatchers.Default
77 | ): Flow = map {
78 | withContext(context) {
79 | it.executeAsOneOrNull()
80 | }
81 | }
82 |
83 | @JvmOverloads
84 | fun Flow>.mapToOneNotNull(
85 | context: CoroutineContext = Dispatchers.Default
86 | ): Flow = mapNotNull {
87 | withContext(context) {
88 | it.executeAsOneOrNull()
89 | }
90 | }
91 |
92 | @JvmOverloads
93 | fun Flow>.mapToList(
94 | context: CoroutineContext = Dispatchers.Default
95 | ): Flow> = map {
96 | withContext(context) {
97 | it.executeAsList()
98 | }
99 | }
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/webApp/src/jsMain/kotlin/TrendingUI.kt:
--------------------------------------------------------------------------------
1 | import com.baseio.kmm.domain.model.GithubReposItem
2 | import com.baseio.kmm.features.trending.GithubTrendingDataModel
3 | import kotlinx.coroutines.*
4 | import kotlinx.css.Display
5 | import kotlinx.css.FlexDirection
6 | import kotlinx.css.display
7 | import kotlinx.css.flexDirection
8 | import kotlinx.html.js.onChangeFunction
9 | import org.w3c.dom.HTMLInputElement
10 | import react.*
11 | import react.dom.*
12 | import styled.css
13 | import styled.styledDiv
14 |
15 | external interface TrendingProps : Props
16 |
17 | val TrendingUI = fc {
18 | var trendingRepos: List by useState(emptyList())
19 | var message: String by useState("")
20 | var state by useState()
21 | var search by useState("")
22 |
23 | val dataModel = GithubTrendingDataModel(onDataState = { stateNew ->
24 | state = stateNew
25 | when (stateNew) {
26 | is GithubTrendingDataModel.LoadingState -> {
27 | message = "Loading..."
28 | }
29 | is GithubTrendingDataModel.SuccessState -> {
30 | trendingRepos = stateNew.trendingList
31 | message = "Found repos..."
32 | }
33 | GithubTrendingDataModel.Complete -> {
34 | message = "Completed loading!"
35 | }
36 | GithubTrendingDataModel.EmptyState -> {
37 | message = "Emty state"
38 | }
39 | is GithubTrendingDataModel.ErrorState -> {
40 | message = stateNew.throwable.message ?: "Error"
41 | }
42 | }
43 | })
44 |
45 | useEffectOnce {
46 | MainScope().launch {
47 | setupDriver()
48 | message = "Driver created";
49 | dataModel.activate()
50 | message = "DataModel activated";
51 | }
52 | }
53 |
54 | h1 {
55 | +"Trending Kotlin Repositories"
56 | }
57 | h1 {
58 | +"Status :"
59 | +message
60 | }
61 |
62 | styledDiv{
63 | css {
64 | display = Display.flex
65 | flexDirection = FlexDirection.column
66 | }
67 |
68 | div{
69 | input {
70 | attrs{
71 | placeholder = "Search by language..."
72 | value = search
73 | onChangeFunction = {
74 | val target = it.target as HTMLInputElement
75 | search = target.value
76 | }
77 | }
78 | }
79 |
80 | button {
81 | +"Search Now"
82 |
83 | attrs {
84 | onClick = {
85 | dataModel.filterRecords(search)
86 | }
87 | }
88 | }
89 | }
90 |
91 |
92 | }
93 |
94 | h1{
95 |
96 | }
97 |
98 | div {
99 | for (repo in trendingRepos) {
100 | img(src = repo.avatar, classes = "img") {
101 | this.attrs.height = "100"
102 | this.attrs.width = "100"
103 | }
104 | div {
105 | p {
106 | key = repo.url
107 | +"${repo.name}: ${repo.author}"
108 | }
109 | a {
110 | attrs {
111 | href = repo.url.toString()
112 | target = repo.url.toString()
113 | }
114 | p {
115 | +repo.url.toString()
116 | }
117 | }
118 | }
119 |
120 | }
121 | }
122 |
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/shared/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | CommonPlugins.plugins.forEach { dependency ->
3 | id(dependency)
4 | }
5 | CommonPlugins.kotlinPlugins.forEach { dependency ->
6 | kotlin(dependency)
7 | }
8 | }
9 |
10 | version = "1.0"
11 |
12 | kotlin {
13 | targets{
14 | android()
15 | iosX64()
16 | iosArm64()
17 | watchos()
18 | macosX64()
19 | macosArm64()
20 | watchosSimulatorArm64()
21 | iosSimulatorArm64() // sure all ios dependencies support this target
22 | jvm("desktop") {
23 | compilations.all {
24 | kotlinOptions.jvmTarget = "11"
25 | }
26 | }
27 | js(IR) {
28 | binaries.executable()
29 | browser {
30 | commonWebpackConfig {
31 | cssSupport.enabled = true
32 | }
33 | }
34 | }
35 | }
36 |
37 | cocoapods {
38 | summary = "Some description for the Shared Module"
39 | homepage = "Link to the Shared Module homepage"
40 | ios.deploymentTarget = "14.1"
41 | podfile = project.file("../iosApp/Podfile")
42 | framework {
43 | baseName = "shared"
44 | }
45 | }
46 |
47 | sourceSets {
48 | val commonMain by getting {
49 | dependencies {
50 | CommonMainDependencies.implementation.forEach(::implementation)
51 | CommonMainDependencies.api.forEach(::api)
52 | }
53 | }
54 | val commonTest by getting {
55 | dependencies {
56 | CommonTestDependencies.implementation.forEach(::implementation)
57 | CommonTestDependencies.kotlin.map { dependency ->
58 | kotlin(dependency)
59 | }.forEach(::implementation)
60 | }
61 | }
62 | val androidMain by getting {
63 | dependencies {
64 | AndroidMainDependencies.implementation.forEach(::implementation)
65 | }
66 | }
67 | val desktopMain by getting {
68 | dependencies {
69 | ComposeDesktopDependencies.implementation.forEach(::implementation)
70 | }
71 | }
72 |
73 | val androidTest by getting {
74 | dependencies {
75 | AndroidTestDependencies.kotlin.map { dependency ->
76 | kotlin(dependency)
77 | }.forEach(::implementation)
78 | AndroidTestDependencies.implementation.forEach(::implementation)
79 | }
80 | }
81 | val jsMain by getting {
82 | dependencies {
83 | WebAppCommonMainDependencies.implementation.forEach(::implementation)
84 | }
85 | }
86 | val iosX64Main by getting
87 | val iosArm64Main by getting
88 | val iosSimulatorArm64Main by getting
89 |
90 | val watchosSimulatorArm64Main by getting
91 | val watchosMain by getting
92 |
93 | val macosX64Main by getting {
94 | dependencies {
95 | MacOSMainDependencies.implementationx64.forEach(::implementation)
96 | }
97 | }
98 | val macosArm64Main by getting {
99 | dependencies {
100 | MacOSMainDependencies.implementationArm64.forEach(::implementation)
101 | }
102 | }
103 |
104 | val iosMain by creating {
105 | dependencies {
106 | IOSMainDependencies.implementation.forEach(::implementation)
107 | }
108 | dependsOn(commonMain)
109 | watchosMain.dependsOn(this)
110 | watchosSimulatorArm64Main.dependsOn(this)
111 | iosX64Main.dependsOn(this)
112 | iosArm64Main.dependsOn(this)
113 | iosSimulatorArm64Main.dependsOn(this)
114 | }
115 | val iosX64Test by getting
116 | val iosArm64Test by getting
117 | val iosSimulatorArm64Test by getting
118 | val iosTest by creating {
119 | dependsOn(commonTest)
120 | iosX64Test.dependsOn(this)
121 | iosArm64Test.dependsOn(this)
122 | iosSimulatorArm64Test.dependsOn(this)
123 | }
124 | }
125 | }
126 |
127 |
128 | tasks.withType {
129 | kotlinOptions {
130 | jvmTarget = "1.8"
131 | }
132 | }
133 |
134 |
135 | sqldelight {
136 | database("BaseIoDB") {
137 | packageName = "com.baseio.kmm.db"
138 | }
139 | }
140 |
141 | android {
142 | compileSdk = 31
143 | sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
144 | defaultConfig {
145 | minSdk = 21
146 | targetSdk = 31
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/iosApp/iosApp.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 51;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557BA273AAA24004C7B11 /* Assets.xcassets */; };
11 | 058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; };
12 | 12F72EEE657317AD0347C1FB /* Pods_iosApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2653B26BCBC847F765B563C5 /* Pods_iosApp.framework */; };
13 | 2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iOSApp.swift */; };
14 | 7555FF83242A565900829871 /* GithubTrendingUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* GithubTrendingUI.swift */; };
15 | 89D841702779CFB200D08BC0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D8416F2779CFB200D08BC0 /* AppDelegate.swift */; };
16 | 89D841732779D83600D08BC0 /* GithubTrendingVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D841722779D83600D08BC0 /* GithubTrendingVM.swift */; };
17 | 89D841752779D8CD00D08BC0 /* UiRepo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D841742779D8CD00D08BC0 /* UiRepo.swift */; };
18 | /* End PBXBuildFile section */
19 |
20 | /* Begin PBXFileReference section */
21 | 058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
22 | 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
23 | 2152FB032600AC8F00CF470E /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = ""; };
24 | 2653B26BCBC847F765B563C5 /* Pods_iosApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iosApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
25 | 7555FF7B242A565900829871 /* iosApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
26 | 7555FF82242A565900829871 /* GithubTrendingUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GithubTrendingUI.swift; sourceTree = ""; };
27 | 7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
28 | 89D8416F2779CFB200D08BC0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
29 | 89D841722779D83600D08BC0 /* GithubTrendingVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GithubTrendingVM.swift; sourceTree = ""; };
30 | 89D841742779D8CD00D08BC0 /* UiRepo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UiRepo.swift; sourceTree = ""; };
31 | 95A4C568919CD765F48B4C71 /* Pods-iosApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iosApp.debug.xcconfig"; path = "Target Support Files/Pods-iosApp/Pods-iosApp.debug.xcconfig"; sourceTree = ""; };
32 | C000B12582D1C9BAAF385E15 /* Pods-iosApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iosApp.release.xcconfig"; path = "Target Support Files/Pods-iosApp/Pods-iosApp.release.xcconfig"; sourceTree = ""; };
33 | /* End PBXFileReference section */
34 |
35 | /* Begin PBXFrameworksBuildPhase section */
36 | 2B5F32FB34CAAB6EAE5E80A8 /* Frameworks */ = {
37 | isa = PBXFrameworksBuildPhase;
38 | buildActionMask = 2147483647;
39 | files = (
40 | 12F72EEE657317AD0347C1FB /* Pods_iosApp.framework in Frameworks */,
41 | );
42 | runOnlyForDeploymentPostprocessing = 0;
43 | };
44 | /* End PBXFrameworksBuildPhase section */
45 |
46 | /* Begin PBXGroup section */
47 | 058557D7273AAEEB004C7B11 /* Preview Content */ = {
48 | isa = PBXGroup;
49 | children = (
50 | 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */,
51 | );
52 | path = "Preview Content";
53 | sourceTree = "";
54 | };
55 | 43284C8CA9782B61E3903EBC /* Pods */ = {
56 | isa = PBXGroup;
57 | children = (
58 | 95A4C568919CD765F48B4C71 /* Pods-iosApp.debug.xcconfig */,
59 | C000B12582D1C9BAAF385E15 /* Pods-iosApp.release.xcconfig */,
60 | );
61 | path = Pods;
62 | sourceTree = "";
63 | };
64 | 4443D9C6DE2DF5582B9E9D06 /* Frameworks */ = {
65 | isa = PBXGroup;
66 | children = (
67 | 2653B26BCBC847F765B563C5 /* Pods_iosApp.framework */,
68 | );
69 | name = Frameworks;
70 | sourceTree = "";
71 | };
72 | 7555FF72242A565900829871 = {
73 | isa = PBXGroup;
74 | children = (
75 | 7555FF7D242A565900829871 /* iosApp */,
76 | 7555FF7C242A565900829871 /* Products */,
77 | 43284C8CA9782B61E3903EBC /* Pods */,
78 | 4443D9C6DE2DF5582B9E9D06 /* Frameworks */,
79 | );
80 | sourceTree = "";
81 | };
82 | 7555FF7C242A565900829871 /* Products */ = {
83 | isa = PBXGroup;
84 | children = (
85 | 7555FF7B242A565900829871 /* iosApp.app */,
86 | );
87 | name = Products;
88 | sourceTree = "";
89 | };
90 | 7555FF7D242A565900829871 /* iosApp */ = {
91 | isa = PBXGroup;
92 | children = (
93 | 89D841712779D5E300D08BC0 /* githubtrending */,
94 | 058557BA273AAA24004C7B11 /* Assets.xcassets */,
95 | 7555FF8C242A565B00829871 /* Info.plist */,
96 | 2152FB032600AC8F00CF470E /* iOSApp.swift */,
97 | 058557D7273AAEEB004C7B11 /* Preview Content */,
98 | 89D8416F2779CFB200D08BC0 /* AppDelegate.swift */,
99 | );
100 | path = iosApp;
101 | sourceTree = "";
102 | };
103 | 89D841712779D5E300D08BC0 /* githubtrending */ = {
104 | isa = PBXGroup;
105 | children = (
106 | 7555FF82242A565900829871 /* GithubTrendingUI.swift */,
107 | 89D841722779D83600D08BC0 /* GithubTrendingVM.swift */,
108 | 89D841742779D8CD00D08BC0 /* UiRepo.swift */,
109 | );
110 | path = githubtrending;
111 | sourceTree = "";
112 | };
113 | /* End PBXGroup section */
114 |
115 | /* Begin PBXNativeTarget section */
116 | 7555FF7A242A565900829871 /* iosApp */ = {
117 | isa = PBXNativeTarget;
118 | buildConfigurationList = 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */;
119 | buildPhases = (
120 | EA1B7D0D1D69916276B38A29 /* [CP] Check Pods Manifest.lock */,
121 | 7555FF77242A565900829871 /* Sources */,
122 | 7555FF79242A565900829871 /* Resources */,
123 | 2B5F32FB34CAAB6EAE5E80A8 /* Frameworks */,
124 | 31FE1465BD3A5C7508CDDA0D /* [CP] Embed Pods Frameworks */,
125 | );
126 | buildRules = (
127 | );
128 | dependencies = (
129 | );
130 | name = iosApp;
131 | productName = iosApp;
132 | productReference = 7555FF7B242A565900829871 /* iosApp.app */;
133 | productType = "com.apple.product-type.application";
134 | };
135 | /* End PBXNativeTarget section */
136 |
137 | /* Begin PBXProject section */
138 | 7555FF73242A565900829871 /* Project object */ = {
139 | isa = PBXProject;
140 | attributes = {
141 | LastSwiftUpdateCheck = 1130;
142 | LastUpgradeCheck = 1130;
143 | ORGANIZATIONNAME = orgName;
144 | TargetAttributes = {
145 | 7555FF7A242A565900829871 = {
146 | CreatedOnToolsVersion = 11.3.1;
147 | };
148 | };
149 | };
150 | buildConfigurationList = 7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */;
151 | compatibilityVersion = "Xcode 9.3";
152 | developmentRegion = en;
153 | hasScannedForEncodings = 0;
154 | knownRegions = (
155 | en,
156 | Base,
157 | );
158 | mainGroup = 7555FF72242A565900829871;
159 | productRefGroup = 7555FF7C242A565900829871 /* Products */;
160 | projectDirPath = "";
161 | projectRoot = "";
162 | targets = (
163 | 7555FF7A242A565900829871 /* iosApp */,
164 | );
165 | };
166 | /* End PBXProject section */
167 |
168 | /* Begin PBXResourcesBuildPhase section */
169 | 7555FF79242A565900829871 /* Resources */ = {
170 | isa = PBXResourcesBuildPhase;
171 | buildActionMask = 2147483647;
172 | files = (
173 | 058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */,
174 | 058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */,
175 | );
176 | runOnlyForDeploymentPostprocessing = 0;
177 | };
178 | /* End PBXResourcesBuildPhase section */
179 |
180 | /* Begin PBXShellScriptBuildPhase section */
181 | 31FE1465BD3A5C7508CDDA0D /* [CP] Embed Pods Frameworks */ = {
182 | isa = PBXShellScriptBuildPhase;
183 | buildActionMask = 2147483647;
184 | files = (
185 | );
186 | inputFileListPaths = (
187 | "${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks-${CONFIGURATION}-input-files.xcfilelist",
188 | );
189 | name = "[CP] Embed Pods Frameworks";
190 | outputFileListPaths = (
191 | "${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks-${CONFIGURATION}-output-files.xcfilelist",
192 | );
193 | runOnlyForDeploymentPostprocessing = 0;
194 | shellPath = /bin/sh;
195 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-iosApp/Pods-iosApp-frameworks.sh\"\n";
196 | showEnvVarsInLog = 0;
197 | };
198 | EA1B7D0D1D69916276B38A29 /* [CP] Check Pods Manifest.lock */ = {
199 | isa = PBXShellScriptBuildPhase;
200 | buildActionMask = 2147483647;
201 | files = (
202 | );
203 | inputFileListPaths = (
204 | );
205 | inputPaths = (
206 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
207 | "${PODS_ROOT}/Manifest.lock",
208 | );
209 | name = "[CP] Check Pods Manifest.lock";
210 | outputFileListPaths = (
211 | );
212 | outputPaths = (
213 | "$(DERIVED_FILE_DIR)/Pods-iosApp-checkManifestLockResult.txt",
214 | );
215 | runOnlyForDeploymentPostprocessing = 0;
216 | shellPath = /bin/sh;
217 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
218 | showEnvVarsInLog = 0;
219 | };
220 | /* End PBXShellScriptBuildPhase section */
221 |
222 | /* Begin PBXSourcesBuildPhase section */
223 | 7555FF77242A565900829871 /* Sources */ = {
224 | isa = PBXSourcesBuildPhase;
225 | buildActionMask = 2147483647;
226 | files = (
227 | 89D841702779CFB200D08BC0 /* AppDelegate.swift in Sources */,
228 | 89D841752779D8CD00D08BC0 /* UiRepo.swift in Sources */,
229 | 2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */,
230 | 89D841732779D83600D08BC0 /* GithubTrendingVM.swift in Sources */,
231 | 7555FF83242A565900829871 /* GithubTrendingUI.swift in Sources */,
232 | );
233 | runOnlyForDeploymentPostprocessing = 0;
234 | };
235 | /* End PBXSourcesBuildPhase section */
236 |
237 | /* Begin XCBuildConfiguration section */
238 | 7555FFA3242A565B00829871 /* Debug */ = {
239 | isa = XCBuildConfiguration;
240 | buildSettings = {
241 | ALWAYS_SEARCH_USER_PATHS = NO;
242 | CLANG_ANALYZER_NONNULL = YES;
243 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
244 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
245 | CLANG_CXX_LIBRARY = "libc++";
246 | CLANG_ENABLE_MODULES = YES;
247 | CLANG_ENABLE_OBJC_ARC = YES;
248 | CLANG_ENABLE_OBJC_WEAK = YES;
249 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
250 | CLANG_WARN_BOOL_CONVERSION = YES;
251 | CLANG_WARN_COMMA = YES;
252 | CLANG_WARN_CONSTANT_CONVERSION = YES;
253 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
254 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
255 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
256 | CLANG_WARN_EMPTY_BODY = YES;
257 | CLANG_WARN_ENUM_CONVERSION = YES;
258 | CLANG_WARN_INFINITE_RECURSION = YES;
259 | CLANG_WARN_INT_CONVERSION = YES;
260 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
261 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
262 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
263 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
264 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
265 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
266 | CLANG_WARN_STRICT_PROTOTYPES = YES;
267 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
268 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
269 | CLANG_WARN_UNREACHABLE_CODE = YES;
270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
271 | COPY_PHASE_STRIP = NO;
272 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
273 | ENABLE_STRICT_OBJC_MSGSEND = YES;
274 | ENABLE_TESTABILITY = YES;
275 | GCC_C_LANGUAGE_STANDARD = gnu11;
276 | GCC_DYNAMIC_NO_PIC = NO;
277 | GCC_NO_COMMON_BLOCKS = YES;
278 | GCC_OPTIMIZATION_LEVEL = 0;
279 | GCC_PREPROCESSOR_DEFINITIONS = (
280 | "DEBUG=1",
281 | "$(inherited)",
282 | );
283 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
284 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
285 | GCC_WARN_UNDECLARED_SELECTOR = YES;
286 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
287 | GCC_WARN_UNUSED_FUNCTION = YES;
288 | GCC_WARN_UNUSED_VARIABLE = YES;
289 | IPHONEOS_DEPLOYMENT_TARGET = 14.1;
290 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
291 | MTL_FAST_MATH = YES;
292 | ONLY_ACTIVE_ARCH = YES;
293 | SDKROOT = iphoneos;
294 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
295 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
296 | };
297 | name = Debug;
298 | };
299 | 7555FFA4242A565B00829871 /* Release */ = {
300 | isa = XCBuildConfiguration;
301 | buildSettings = {
302 | ALWAYS_SEARCH_USER_PATHS = NO;
303 | CLANG_ANALYZER_NONNULL = YES;
304 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
305 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
306 | CLANG_CXX_LIBRARY = "libc++";
307 | CLANG_ENABLE_MODULES = YES;
308 | CLANG_ENABLE_OBJC_ARC = YES;
309 | CLANG_ENABLE_OBJC_WEAK = YES;
310 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
311 | CLANG_WARN_BOOL_CONVERSION = YES;
312 | CLANG_WARN_COMMA = YES;
313 | CLANG_WARN_CONSTANT_CONVERSION = YES;
314 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
315 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
316 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
317 | CLANG_WARN_EMPTY_BODY = YES;
318 | CLANG_WARN_ENUM_CONVERSION = YES;
319 | CLANG_WARN_INFINITE_RECURSION = YES;
320 | CLANG_WARN_INT_CONVERSION = YES;
321 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
322 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
323 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
325 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
326 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
327 | CLANG_WARN_STRICT_PROTOTYPES = YES;
328 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
329 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
330 | CLANG_WARN_UNREACHABLE_CODE = YES;
331 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
332 | COPY_PHASE_STRIP = NO;
333 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
334 | ENABLE_NS_ASSERTIONS = NO;
335 | ENABLE_STRICT_OBJC_MSGSEND = YES;
336 | GCC_C_LANGUAGE_STANDARD = gnu11;
337 | GCC_NO_COMMON_BLOCKS = YES;
338 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
339 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
340 | GCC_WARN_UNDECLARED_SELECTOR = YES;
341 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
342 | GCC_WARN_UNUSED_FUNCTION = YES;
343 | GCC_WARN_UNUSED_VARIABLE = YES;
344 | IPHONEOS_DEPLOYMENT_TARGET = 14.1;
345 | MTL_ENABLE_DEBUG_INFO = NO;
346 | MTL_FAST_MATH = YES;
347 | SDKROOT = iphoneos;
348 | SWIFT_COMPILATION_MODE = wholemodule;
349 | SWIFT_OPTIMIZATION_LEVEL = "-O";
350 | VALIDATE_PRODUCT = YES;
351 | };
352 | name = Release;
353 | };
354 | 7555FFA6242A565B00829871 /* Debug */ = {
355 | isa = XCBuildConfiguration;
356 | baseConfigurationReference = 95A4C568919CD765F48B4C71 /* Pods-iosApp.debug.xcconfig */;
357 | buildSettings = {
358 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
359 | CODE_SIGN_STYLE = Automatic;
360 | DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
361 | ENABLE_PREVIEWS = YES;
362 | INFOPLIST_FILE = iosApp/Info.plist;
363 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
364 | LD_RUNPATH_SEARCH_PATHS = (
365 | "$(inherited)",
366 | "@executable_path/Frameworks",
367 | );
368 | OTHER_LDFLAGS = (
369 | "$(inherited)",
370 | "-ObjC",
371 | "-l\"c++\"",
372 | "-framework",
373 | "\"KMPNativeCoroutinesCombine\"",
374 | "-framework",
375 | "\"KMPNativeCoroutinesCore\"",
376 | "-framework",
377 | "\"shared\"",
378 | "-lsqlite3",
379 | );
380 | PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp;
381 | PRODUCT_NAME = "$(TARGET_NAME)";
382 | SWIFT_VERSION = 5.0;
383 | TARGETED_DEVICE_FAMILY = "1,2";
384 | };
385 | name = Debug;
386 | };
387 | 7555FFA7242A565B00829871 /* Release */ = {
388 | isa = XCBuildConfiguration;
389 | baseConfigurationReference = C000B12582D1C9BAAF385E15 /* Pods-iosApp.release.xcconfig */;
390 | buildSettings = {
391 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
392 | CODE_SIGN_STYLE = Automatic;
393 | DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
394 | ENABLE_PREVIEWS = YES;
395 | INFOPLIST_FILE = iosApp/Info.plist;
396 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
397 | LD_RUNPATH_SEARCH_PATHS = (
398 | "$(inherited)",
399 | "@executable_path/Frameworks",
400 | );
401 | OTHER_LDFLAGS = (
402 | "$(inherited)",
403 | "-ObjC",
404 | "-l\"c++\"",
405 | "-framework",
406 | "\"KMPNativeCoroutinesCombine\"",
407 | "-framework",
408 | "\"KMPNativeCoroutinesCore\"",
409 | "-framework",
410 | "\"shared\"",
411 | "-lsqlite3",
412 | );
413 | PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp;
414 | PRODUCT_NAME = "$(TARGET_NAME)";
415 | SWIFT_VERSION = 5.0;
416 | TARGETED_DEVICE_FAMILY = "1,2";
417 | };
418 | name = Release;
419 | };
420 | /* End XCBuildConfiguration section */
421 |
422 | /* Begin XCConfigurationList section */
423 | 7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */ = {
424 | isa = XCConfigurationList;
425 | buildConfigurations = (
426 | 7555FFA3242A565B00829871 /* Debug */,
427 | 7555FFA4242A565B00829871 /* Release */,
428 | );
429 | defaultConfigurationIsVisible = 0;
430 | defaultConfigurationName = Release;
431 | };
432 | 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */ = {
433 | isa = XCConfigurationList;
434 | buildConfigurations = (
435 | 7555FFA6242A565B00829871 /* Debug */,
436 | 7555FFA7242A565B00829871 /* Release */,
437 | );
438 | defaultConfigurationIsVisible = 0;
439 | defaultConfigurationName = Release;
440 | };
441 | /* End XCConfigurationList section */
442 | };
443 | rootObject = 7555FF73242A565900829871 /* Project object */;
444 | }
445 |
--------------------------------------------------------------------------------
/macOS/macOS.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 55;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 89D8421F277A218500D08BC0 /* macOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D8421E277A218500D08BC0 /* macOSApp.swift */; };
11 | 89D84223277A218600D08BC0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 89D84222277A218600D08BC0 /* Assets.xcassets */; };
12 | 89D84226277A218600D08BC0 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 89D84225277A218600D08BC0 /* Preview Assets.xcassets */; };
13 | 89D84231277A218600D08BC0 /* macOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D84230277A218600D08BC0 /* macOSTests.swift */; };
14 | 89D8423B277A218600D08BC0 /* macOSUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D8423A277A218600D08BC0 /* macOSUITests.swift */; };
15 | 89D8423D277A218600D08BC0 /* macOSUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D8423C277A218600D08BC0 /* macOSUITestsLaunchTests.swift */; };
16 | 89D84251277A25D100D08BC0 /* GithubTrendingUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D8424E277A25D100D08BC0 /* GithubTrendingUI.swift */; };
17 | 89D84252277A25D100D08BC0 /* UiRepo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D8424F277A25D100D08BC0 /* UiRepo.swift */; };
18 | 89D84253277A25D100D08BC0 /* GithubTrendingVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D84250277A25D100D08BC0 /* GithubTrendingVM.swift */; };
19 | D517D08F8A4365D67D27DE7F /* libPods-macOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EA38324EF8E940C0D06D4CE /* libPods-macOS.a */; };
20 | /* End PBXBuildFile section */
21 |
22 | /* Begin PBXContainerItemProxy section */
23 | 89D8422D277A218600D08BC0 /* PBXContainerItemProxy */ = {
24 | isa = PBXContainerItemProxy;
25 | containerPortal = 89D84213277A218500D08BC0 /* Project object */;
26 | proxyType = 1;
27 | remoteGlobalIDString = 89D8421A277A218500D08BC0;
28 | remoteInfo = macOS;
29 | };
30 | 89D84237277A218600D08BC0 /* PBXContainerItemProxy */ = {
31 | isa = PBXContainerItemProxy;
32 | containerPortal = 89D84213277A218500D08BC0 /* Project object */;
33 | proxyType = 1;
34 | remoteGlobalIDString = 89D8421A277A218500D08BC0;
35 | remoteInfo = macOS;
36 | };
37 | /* End PBXContainerItemProxy section */
38 |
39 | /* Begin PBXFileReference section */
40 | 14536A7C63C12B806054769C /* Pods-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macOS.debug.xcconfig"; path = "Target Support Files/Pods-macOS/Pods-macOS.debug.xcconfig"; sourceTree = ""; };
41 | 1EA38324EF8E940C0D06D4CE /* libPods-macOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-macOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
42 | 854FBFAB66BF3DF25604115C /* Pods-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-macOS.release.xcconfig"; path = "Target Support Files/Pods-macOS/Pods-macOS.release.xcconfig"; sourceTree = ""; };
43 | 89D8421B277A218500D08BC0 /* macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = macOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
44 | 89D8421E277A218500D08BC0 /* macOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = macOSApp.swift; sourceTree = ""; };
45 | 89D84222277A218600D08BC0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
46 | 89D84225277A218600D08BC0 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
47 | 89D84227277A218600D08BC0 /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = ""; };
48 | 89D8422C277A218600D08BC0 /* macOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = macOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
49 | 89D84230277A218600D08BC0 /* macOSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = macOSTests.swift; sourceTree = ""; };
50 | 89D84236277A218600D08BC0 /* macOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = macOSUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
51 | 89D8423A277A218600D08BC0 /* macOSUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = macOSUITests.swift; sourceTree = ""; };
52 | 89D8423C277A218600D08BC0 /* macOSUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = macOSUITestsLaunchTests.swift; sourceTree = ""; };
53 | 89D8424E277A25D100D08BC0 /* GithubTrendingUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GithubTrendingUI.swift; sourceTree = ""; };
54 | 89D8424F277A25D100D08BC0 /* UiRepo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UiRepo.swift; sourceTree = ""; };
55 | 89D84250277A25D100D08BC0 /* GithubTrendingVM.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GithubTrendingVM.swift; sourceTree = ""; };
56 | /* End PBXFileReference section */
57 |
58 | /* Begin PBXFrameworksBuildPhase section */
59 | 89D84218277A218500D08BC0 /* Frameworks */ = {
60 | isa = PBXFrameworksBuildPhase;
61 | buildActionMask = 2147483647;
62 | files = (
63 | D517D08F8A4365D67D27DE7F /* libPods-macOS.a in Frameworks */,
64 | );
65 | runOnlyForDeploymentPostprocessing = 0;
66 | };
67 | 89D84229277A218600D08BC0 /* Frameworks */ = {
68 | isa = PBXFrameworksBuildPhase;
69 | buildActionMask = 2147483647;
70 | files = (
71 | );
72 | runOnlyForDeploymentPostprocessing = 0;
73 | };
74 | 89D84233277A218600D08BC0 /* Frameworks */ = {
75 | isa = PBXFrameworksBuildPhase;
76 | buildActionMask = 2147483647;
77 | files = (
78 | );
79 | runOnlyForDeploymentPostprocessing = 0;
80 | };
81 | /* End PBXFrameworksBuildPhase section */
82 |
83 | /* Begin PBXGroup section */
84 | 403E6E4318611032E81F5AB5 /* Pods */ = {
85 | isa = PBXGroup;
86 | children = (
87 | 14536A7C63C12B806054769C /* Pods-macOS.debug.xcconfig */,
88 | 854FBFAB66BF3DF25604115C /* Pods-macOS.release.xcconfig */,
89 | );
90 | path = Pods;
91 | sourceTree = "";
92 | };
93 | 89D84212277A218500D08BC0 = {
94 | isa = PBXGroup;
95 | children = (
96 | 89D8421D277A218500D08BC0 /* macOS */,
97 | 89D8422F277A218600D08BC0 /* macOSTests */,
98 | 89D84239277A218600D08BC0 /* macOSUITests */,
99 | 89D8421C277A218500D08BC0 /* Products */,
100 | 403E6E4318611032E81F5AB5 /* Pods */,
101 | 8A313E3128877F794EC8E09F /* Frameworks */,
102 | );
103 | sourceTree = "";
104 | };
105 | 89D8421C277A218500D08BC0 /* Products */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 89D8421B277A218500D08BC0 /* macOS.app */,
109 | 89D8422C277A218600D08BC0 /* macOSTests.xctest */,
110 | 89D84236277A218600D08BC0 /* macOSUITests.xctest */,
111 | );
112 | name = Products;
113 | sourceTree = "";
114 | };
115 | 89D8421D277A218500D08BC0 /* macOS */ = {
116 | isa = PBXGroup;
117 | children = (
118 | 89D8424D277A25D100D08BC0 /* githubtrending */,
119 | 89D8421E277A218500D08BC0 /* macOSApp.swift */,
120 | 89D84222277A218600D08BC0 /* Assets.xcassets */,
121 | 89D84227277A218600D08BC0 /* macOS.entitlements */,
122 | 89D84224277A218600D08BC0 /* Preview Content */,
123 | );
124 | path = macOS;
125 | sourceTree = "";
126 | };
127 | 89D84224277A218600D08BC0 /* Preview Content */ = {
128 | isa = PBXGroup;
129 | children = (
130 | 89D84225277A218600D08BC0 /* Preview Assets.xcassets */,
131 | );
132 | path = "Preview Content";
133 | sourceTree = "";
134 | };
135 | 89D8422F277A218600D08BC0 /* macOSTests */ = {
136 | isa = PBXGroup;
137 | children = (
138 | 89D84230277A218600D08BC0 /* macOSTests.swift */,
139 | );
140 | path = macOSTests;
141 | sourceTree = "";
142 | };
143 | 89D84239277A218600D08BC0 /* macOSUITests */ = {
144 | isa = PBXGroup;
145 | children = (
146 | 89D8423A277A218600D08BC0 /* macOSUITests.swift */,
147 | 89D8423C277A218600D08BC0 /* macOSUITestsLaunchTests.swift */,
148 | );
149 | path = macOSUITests;
150 | sourceTree = "";
151 | };
152 | 89D8424D277A25D100D08BC0 /* githubtrending */ = {
153 | isa = PBXGroup;
154 | children = (
155 | 89D8424E277A25D100D08BC0 /* GithubTrendingUI.swift */,
156 | 89D8424F277A25D100D08BC0 /* UiRepo.swift */,
157 | 89D84250277A25D100D08BC0 /* GithubTrendingVM.swift */,
158 | );
159 | path = githubtrending;
160 | sourceTree = "";
161 | };
162 | 8A313E3128877F794EC8E09F /* Frameworks */ = {
163 | isa = PBXGroup;
164 | children = (
165 | 1EA38324EF8E940C0D06D4CE /* libPods-macOS.a */,
166 | );
167 | name = Frameworks;
168 | sourceTree = "";
169 | };
170 | /* End PBXGroup section */
171 |
172 | /* Begin PBXNativeTarget section */
173 | 89D8421A277A218500D08BC0 /* macOS */ = {
174 | isa = PBXNativeTarget;
175 | buildConfigurationList = 89D84240277A218600D08BC0 /* Build configuration list for PBXNativeTarget "macOS" */;
176 | buildPhases = (
177 | 2F083E599676636460651DC1 /* [CP] Check Pods Manifest.lock */,
178 | 89D84217277A218500D08BC0 /* Sources */,
179 | 89D84218277A218500D08BC0 /* Frameworks */,
180 | 89D84219277A218500D08BC0 /* Resources */,
181 | );
182 | buildRules = (
183 | );
184 | dependencies = (
185 | );
186 | name = macOS;
187 | productName = macOS;
188 | productReference = 89D8421B277A218500D08BC0 /* macOS.app */;
189 | productType = "com.apple.product-type.application";
190 | };
191 | 89D8422B277A218600D08BC0 /* macOSTests */ = {
192 | isa = PBXNativeTarget;
193 | buildConfigurationList = 89D84243277A218600D08BC0 /* Build configuration list for PBXNativeTarget "macOSTests" */;
194 | buildPhases = (
195 | 89D84228277A218600D08BC0 /* Sources */,
196 | 89D84229277A218600D08BC0 /* Frameworks */,
197 | 89D8422A277A218600D08BC0 /* Resources */,
198 | );
199 | buildRules = (
200 | );
201 | dependencies = (
202 | 89D8422E277A218600D08BC0 /* PBXTargetDependency */,
203 | );
204 | name = macOSTests;
205 | productName = macOSTests;
206 | productReference = 89D8422C277A218600D08BC0 /* macOSTests.xctest */;
207 | productType = "com.apple.product-type.bundle.unit-test";
208 | };
209 | 89D84235277A218600D08BC0 /* macOSUITests */ = {
210 | isa = PBXNativeTarget;
211 | buildConfigurationList = 89D84246277A218600D08BC0 /* Build configuration list for PBXNativeTarget "macOSUITests" */;
212 | buildPhases = (
213 | 89D84232277A218600D08BC0 /* Sources */,
214 | 89D84233277A218600D08BC0 /* Frameworks */,
215 | 89D84234277A218600D08BC0 /* Resources */,
216 | );
217 | buildRules = (
218 | );
219 | dependencies = (
220 | 89D84238277A218600D08BC0 /* PBXTargetDependency */,
221 | );
222 | name = macOSUITests;
223 | productName = macOSUITests;
224 | productReference = 89D84236277A218600D08BC0 /* macOSUITests.xctest */;
225 | productType = "com.apple.product-type.bundle.ui-testing";
226 | };
227 | /* End PBXNativeTarget section */
228 |
229 | /* Begin PBXProject section */
230 | 89D84213277A218500D08BC0 /* Project object */ = {
231 | isa = PBXProject;
232 | attributes = {
233 | BuildIndependentTargetsInParallel = 1;
234 | LastSwiftUpdateCheck = 1320;
235 | LastUpgradeCheck = 1320;
236 | TargetAttributes = {
237 | 89D8421A277A218500D08BC0 = {
238 | CreatedOnToolsVersion = 13.2.1;
239 | };
240 | 89D8422B277A218600D08BC0 = {
241 | CreatedOnToolsVersion = 13.2.1;
242 | TestTargetID = 89D8421A277A218500D08BC0;
243 | };
244 | 89D84235277A218600D08BC0 = {
245 | CreatedOnToolsVersion = 13.2.1;
246 | TestTargetID = 89D8421A277A218500D08BC0;
247 | };
248 | };
249 | };
250 | buildConfigurationList = 89D84216277A218500D08BC0 /* Build configuration list for PBXProject "macOS" */;
251 | compatibilityVersion = "Xcode 13.0";
252 | developmentRegion = en;
253 | hasScannedForEncodings = 0;
254 | knownRegions = (
255 | en,
256 | Base,
257 | );
258 | mainGroup = 89D84212277A218500D08BC0;
259 | productRefGroup = 89D8421C277A218500D08BC0 /* Products */;
260 | projectDirPath = "";
261 | projectRoot = "";
262 | targets = (
263 | 89D8421A277A218500D08BC0 /* macOS */,
264 | 89D8422B277A218600D08BC0 /* macOSTests */,
265 | 89D84235277A218600D08BC0 /* macOSUITests */,
266 | );
267 | };
268 | /* End PBXProject section */
269 |
270 | /* Begin PBXResourcesBuildPhase section */
271 | 89D84219277A218500D08BC0 /* Resources */ = {
272 | isa = PBXResourcesBuildPhase;
273 | buildActionMask = 2147483647;
274 | files = (
275 | 89D84226277A218600D08BC0 /* Preview Assets.xcassets in Resources */,
276 | 89D84223277A218600D08BC0 /* Assets.xcassets in Resources */,
277 | );
278 | runOnlyForDeploymentPostprocessing = 0;
279 | };
280 | 89D8422A277A218600D08BC0 /* Resources */ = {
281 | isa = PBXResourcesBuildPhase;
282 | buildActionMask = 2147483647;
283 | files = (
284 | );
285 | runOnlyForDeploymentPostprocessing = 0;
286 | };
287 | 89D84234277A218600D08BC0 /* Resources */ = {
288 | isa = PBXResourcesBuildPhase;
289 | buildActionMask = 2147483647;
290 | files = (
291 | );
292 | runOnlyForDeploymentPostprocessing = 0;
293 | };
294 | /* End PBXResourcesBuildPhase section */
295 |
296 | /* Begin PBXShellScriptBuildPhase section */
297 | 2F083E599676636460651DC1 /* [CP] Check Pods Manifest.lock */ = {
298 | isa = PBXShellScriptBuildPhase;
299 | buildActionMask = 2147483647;
300 | files = (
301 | );
302 | inputFileListPaths = (
303 | );
304 | inputPaths = (
305 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
306 | "${PODS_ROOT}/Manifest.lock",
307 | );
308 | name = "[CP] Check Pods Manifest.lock";
309 | outputFileListPaths = (
310 | );
311 | outputPaths = (
312 | "$(DERIVED_FILE_DIR)/Pods-macOS-checkManifestLockResult.txt",
313 | );
314 | runOnlyForDeploymentPostprocessing = 0;
315 | shellPath = /bin/sh;
316 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
317 | showEnvVarsInLog = 0;
318 | };
319 | /* End PBXShellScriptBuildPhase section */
320 |
321 | /* Begin PBXSourcesBuildPhase section */
322 | 89D84217277A218500D08BC0 /* Sources */ = {
323 | isa = PBXSourcesBuildPhase;
324 | buildActionMask = 2147483647;
325 | files = (
326 | 89D84253277A25D100D08BC0 /* GithubTrendingVM.swift in Sources */,
327 | 89D84251277A25D100D08BC0 /* GithubTrendingUI.swift in Sources */,
328 | 89D8421F277A218500D08BC0 /* macOSApp.swift in Sources */,
329 | 89D84252277A25D100D08BC0 /* UiRepo.swift in Sources */,
330 | );
331 | runOnlyForDeploymentPostprocessing = 0;
332 | };
333 | 89D84228277A218600D08BC0 /* Sources */ = {
334 | isa = PBXSourcesBuildPhase;
335 | buildActionMask = 2147483647;
336 | files = (
337 | 89D84231277A218600D08BC0 /* macOSTests.swift in Sources */,
338 | );
339 | runOnlyForDeploymentPostprocessing = 0;
340 | };
341 | 89D84232277A218600D08BC0 /* Sources */ = {
342 | isa = PBXSourcesBuildPhase;
343 | buildActionMask = 2147483647;
344 | files = (
345 | 89D8423D277A218600D08BC0 /* macOSUITestsLaunchTests.swift in Sources */,
346 | 89D8423B277A218600D08BC0 /* macOSUITests.swift in Sources */,
347 | );
348 | runOnlyForDeploymentPostprocessing = 0;
349 | };
350 | /* End PBXSourcesBuildPhase section */
351 |
352 | /* Begin PBXTargetDependency section */
353 | 89D8422E277A218600D08BC0 /* PBXTargetDependency */ = {
354 | isa = PBXTargetDependency;
355 | target = 89D8421A277A218500D08BC0 /* macOS */;
356 | targetProxy = 89D8422D277A218600D08BC0 /* PBXContainerItemProxy */;
357 | };
358 | 89D84238277A218600D08BC0 /* PBXTargetDependency */ = {
359 | isa = PBXTargetDependency;
360 | target = 89D8421A277A218500D08BC0 /* macOS */;
361 | targetProxy = 89D84237277A218600D08BC0 /* PBXContainerItemProxy */;
362 | };
363 | /* End PBXTargetDependency section */
364 |
365 | /* Begin XCBuildConfiguration section */
366 | 89D8423E277A218600D08BC0 /* Debug */ = {
367 | isa = XCBuildConfiguration;
368 | buildSettings = {
369 | ALWAYS_SEARCH_USER_PATHS = NO;
370 | CLANG_ANALYZER_NONNULL = YES;
371 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
372 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
373 | CLANG_CXX_LIBRARY = "libc++";
374 | CLANG_ENABLE_MODULES = YES;
375 | CLANG_ENABLE_OBJC_ARC = YES;
376 | CLANG_ENABLE_OBJC_WEAK = YES;
377 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
378 | CLANG_WARN_BOOL_CONVERSION = YES;
379 | CLANG_WARN_COMMA = YES;
380 | CLANG_WARN_CONSTANT_CONVERSION = YES;
381 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
382 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
383 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
384 | CLANG_WARN_EMPTY_BODY = YES;
385 | CLANG_WARN_ENUM_CONVERSION = YES;
386 | CLANG_WARN_INFINITE_RECURSION = YES;
387 | CLANG_WARN_INT_CONVERSION = YES;
388 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
389 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
390 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
391 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
392 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
393 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
394 | CLANG_WARN_STRICT_PROTOTYPES = YES;
395 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
396 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
397 | CLANG_WARN_UNREACHABLE_CODE = YES;
398 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
399 | COPY_PHASE_STRIP = NO;
400 | DEBUG_INFORMATION_FORMAT = dwarf;
401 | ENABLE_STRICT_OBJC_MSGSEND = YES;
402 | ENABLE_TESTABILITY = YES;
403 | GCC_C_LANGUAGE_STANDARD = gnu11;
404 | GCC_DYNAMIC_NO_PIC = NO;
405 | GCC_NO_COMMON_BLOCKS = YES;
406 | GCC_OPTIMIZATION_LEVEL = 0;
407 | GCC_PREPROCESSOR_DEFINITIONS = (
408 | "DEBUG=1",
409 | "$(inherited)",
410 | );
411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
412 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
413 | GCC_WARN_UNDECLARED_SELECTOR = YES;
414 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
415 | GCC_WARN_UNUSED_FUNCTION = YES;
416 | GCC_WARN_UNUSED_VARIABLE = YES;
417 | MACOSX_DEPLOYMENT_TARGET = 12.0;
418 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
419 | MTL_FAST_MATH = YES;
420 | ONLY_ACTIVE_ARCH = YES;
421 | SDKROOT = macosx;
422 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
423 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
424 | };
425 | name = Debug;
426 | };
427 | 89D8423F277A218600D08BC0 /* Release */ = {
428 | isa = XCBuildConfiguration;
429 | buildSettings = {
430 | ALWAYS_SEARCH_USER_PATHS = NO;
431 | CLANG_ANALYZER_NONNULL = YES;
432 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
433 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
434 | CLANG_CXX_LIBRARY = "libc++";
435 | CLANG_ENABLE_MODULES = YES;
436 | CLANG_ENABLE_OBJC_ARC = YES;
437 | CLANG_ENABLE_OBJC_WEAK = YES;
438 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
439 | CLANG_WARN_BOOL_CONVERSION = YES;
440 | CLANG_WARN_COMMA = YES;
441 | CLANG_WARN_CONSTANT_CONVERSION = YES;
442 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
443 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
444 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
445 | CLANG_WARN_EMPTY_BODY = YES;
446 | CLANG_WARN_ENUM_CONVERSION = YES;
447 | CLANG_WARN_INFINITE_RECURSION = YES;
448 | CLANG_WARN_INT_CONVERSION = YES;
449 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
450 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
451 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
452 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
453 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
454 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
455 | CLANG_WARN_STRICT_PROTOTYPES = YES;
456 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
457 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
458 | CLANG_WARN_UNREACHABLE_CODE = YES;
459 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
460 | COPY_PHASE_STRIP = NO;
461 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
462 | ENABLE_NS_ASSERTIONS = NO;
463 | ENABLE_STRICT_OBJC_MSGSEND = YES;
464 | GCC_C_LANGUAGE_STANDARD = gnu11;
465 | GCC_NO_COMMON_BLOCKS = YES;
466 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
467 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
468 | GCC_WARN_UNDECLARED_SELECTOR = YES;
469 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
470 | GCC_WARN_UNUSED_FUNCTION = YES;
471 | GCC_WARN_UNUSED_VARIABLE = YES;
472 | MACOSX_DEPLOYMENT_TARGET = 12.0;
473 | MTL_ENABLE_DEBUG_INFO = NO;
474 | MTL_FAST_MATH = YES;
475 | SDKROOT = macosx;
476 | SWIFT_COMPILATION_MODE = wholemodule;
477 | SWIFT_OPTIMIZATION_LEVEL = "-O";
478 | };
479 | name = Release;
480 | };
481 | 89D84241277A218600D08BC0 /* Debug */ = {
482 | isa = XCBuildConfiguration;
483 | baseConfigurationReference = 14536A7C63C12B806054769C /* Pods-macOS.debug.xcconfig */;
484 | buildSettings = {
485 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
486 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
487 | CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
488 | CODE_SIGN_STYLE = Automatic;
489 | COMBINE_HIDPI_IMAGES = YES;
490 | CURRENT_PROJECT_VERSION = 1;
491 | DEVELOPMENT_ASSET_PATHS = "\"macOS/Preview Content\"";
492 | DEVELOPMENT_TEAM = S4G3GQXM69;
493 | ENABLE_HARDENED_RUNTIME = YES;
494 | ENABLE_PREVIEWS = YES;
495 | GENERATE_INFOPLIST_FILE = YES;
496 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
497 | LD_RUNPATH_SEARCH_PATHS = (
498 | "$(inherited)",
499 | "@executable_path/../Frameworks",
500 | );
501 | MARKETING_VERSION = 1.0;
502 | OTHER_LDFLAGS = (
503 | "$(inherited)",
504 | "-ObjC",
505 | "-l\"KMPNativeCoroutinesCombine\"",
506 | "-l\"KMPNativeCoroutinesCore\"",
507 | "-l\"c++\"",
508 | "-framework",
509 | "\"Combine\"",
510 | "-framework",
511 | "\"shared\"",
512 | "\"-lsqlite3\"",
513 | );
514 | PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp.macOS;
515 | PRODUCT_NAME = "$(TARGET_NAME)";
516 | SWIFT_EMIT_LOC_STRINGS = YES;
517 | SWIFT_VERSION = 5.0;
518 | };
519 | name = Debug;
520 | };
521 | 89D84242277A218600D08BC0 /* Release */ = {
522 | isa = XCBuildConfiguration;
523 | baseConfigurationReference = 854FBFAB66BF3DF25604115C /* Pods-macOS.release.xcconfig */;
524 | buildSettings = {
525 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
526 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
527 | CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
528 | CODE_SIGN_STYLE = Automatic;
529 | COMBINE_HIDPI_IMAGES = YES;
530 | CURRENT_PROJECT_VERSION = 1;
531 | DEVELOPMENT_ASSET_PATHS = "\"macOS/Preview Content\"";
532 | DEVELOPMENT_TEAM = S4G3GQXM69;
533 | ENABLE_HARDENED_RUNTIME = YES;
534 | ENABLE_PREVIEWS = YES;
535 | GENERATE_INFOPLIST_FILE = YES;
536 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
537 | LD_RUNPATH_SEARCH_PATHS = (
538 | "$(inherited)",
539 | "@executable_path/../Frameworks",
540 | );
541 | MARKETING_VERSION = 1.0;
542 | OTHER_LDFLAGS = (
543 | "$(inherited)",
544 | "-ObjC",
545 | "-l\"KMPNativeCoroutinesCombine\"",
546 | "-l\"KMPNativeCoroutinesCore\"",
547 | "-l\"c++\"",
548 | "-framework",
549 | "\"Combine\"",
550 | "-framework",
551 | "\"shared\"",
552 | "\"-lsqlite3\"",
553 | );
554 | PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp.macOS;
555 | PRODUCT_NAME = "$(TARGET_NAME)";
556 | SWIFT_EMIT_LOC_STRINGS = YES;
557 | SWIFT_VERSION = 5.0;
558 | };
559 | name = Release;
560 | };
561 | 89D84244277A218600D08BC0 /* Debug */ = {
562 | isa = XCBuildConfiguration;
563 | buildSettings = {
564 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
565 | BUNDLE_LOADER = "$(TEST_HOST)";
566 | CODE_SIGN_STYLE = Automatic;
567 | CURRENT_PROJECT_VERSION = 1;
568 | DEVELOPMENT_TEAM = S4G3GQXM69;
569 | GENERATE_INFOPLIST_FILE = YES;
570 | MACOSX_DEPLOYMENT_TARGET = 12.0;
571 | MARKETING_VERSION = 1.0;
572 | PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp.macOSTests;
573 | PRODUCT_NAME = "$(TARGET_NAME)";
574 | SWIFT_EMIT_LOC_STRINGS = NO;
575 | SWIFT_VERSION = 5.0;
576 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/macOS.app/Contents/MacOS/macOS";
577 | };
578 | name = Debug;
579 | };
580 | 89D84245277A218600D08BC0 /* Release */ = {
581 | isa = XCBuildConfiguration;
582 | buildSettings = {
583 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
584 | BUNDLE_LOADER = "$(TEST_HOST)";
585 | CODE_SIGN_STYLE = Automatic;
586 | CURRENT_PROJECT_VERSION = 1;
587 | DEVELOPMENT_TEAM = S4G3GQXM69;
588 | GENERATE_INFOPLIST_FILE = YES;
589 | MACOSX_DEPLOYMENT_TARGET = 12.0;
590 | MARKETING_VERSION = 1.0;
591 | PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp.macOSTests;
592 | PRODUCT_NAME = "$(TARGET_NAME)";
593 | SWIFT_EMIT_LOC_STRINGS = NO;
594 | SWIFT_VERSION = 5.0;
595 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/macOS.app/Contents/MacOS/macOS";
596 | };
597 | name = Release;
598 | };
599 | 89D84247277A218600D08BC0 /* Debug */ = {
600 | isa = XCBuildConfiguration;
601 | buildSettings = {
602 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
603 | CODE_SIGN_STYLE = Automatic;
604 | CURRENT_PROJECT_VERSION = 1;
605 | DEVELOPMENT_TEAM = S4G3GQXM69;
606 | GENERATE_INFOPLIST_FILE = YES;
607 | MARKETING_VERSION = 1.0;
608 | PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp.macOSUITests;
609 | PRODUCT_NAME = "$(TARGET_NAME)";
610 | SWIFT_EMIT_LOC_STRINGS = NO;
611 | SWIFT_VERSION = 5.0;
612 | TEST_TARGET_NAME = macOS;
613 | };
614 | name = Debug;
615 | };
616 | 89D84248277A218600D08BC0 /* Release */ = {
617 | isa = XCBuildConfiguration;
618 | buildSettings = {
619 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
620 | CODE_SIGN_STYLE = Automatic;
621 | CURRENT_PROJECT_VERSION = 1;
622 | DEVELOPMENT_TEAM = S4G3GQXM69;
623 | GENERATE_INFOPLIST_FILE = YES;
624 | MARKETING_VERSION = 1.0;
625 | PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp.macOSUITests;
626 | PRODUCT_NAME = "$(TARGET_NAME)";
627 | SWIFT_EMIT_LOC_STRINGS = NO;
628 | SWIFT_VERSION = 5.0;
629 | TEST_TARGET_NAME = macOS;
630 | };
631 | name = Release;
632 | };
633 | /* End XCBuildConfiguration section */
634 |
635 | /* Begin XCConfigurationList section */
636 | 89D84216277A218500D08BC0 /* Build configuration list for PBXProject "macOS" */ = {
637 | isa = XCConfigurationList;
638 | buildConfigurations = (
639 | 89D8423E277A218600D08BC0 /* Debug */,
640 | 89D8423F277A218600D08BC0 /* Release */,
641 | );
642 | defaultConfigurationIsVisible = 0;
643 | defaultConfigurationName = Release;
644 | };
645 | 89D84240277A218600D08BC0 /* Build configuration list for PBXNativeTarget "macOS" */ = {
646 | isa = XCConfigurationList;
647 | buildConfigurations = (
648 | 89D84241277A218600D08BC0 /* Debug */,
649 | 89D84242277A218600D08BC0 /* Release */,
650 | );
651 | defaultConfigurationIsVisible = 0;
652 | defaultConfigurationName = Release;
653 | };
654 | 89D84243277A218600D08BC0 /* Build configuration list for PBXNativeTarget "macOSTests" */ = {
655 | isa = XCConfigurationList;
656 | buildConfigurations = (
657 | 89D84244277A218600D08BC0 /* Debug */,
658 | 89D84245277A218600D08BC0 /* Release */,
659 | );
660 | defaultConfigurationIsVisible = 0;
661 | defaultConfigurationName = Release;
662 | };
663 | 89D84246277A218600D08BC0 /* Build configuration list for PBXNativeTarget "macOSUITests" */ = {
664 | isa = XCConfigurationList;
665 | buildConfigurations = (
666 | 89D84247277A218600D08BC0 /* Debug */,
667 | 89D84248277A218600D08BC0 /* Release */,
668 | );
669 | defaultConfigurationIsVisible = 0;
670 | defaultConfigurationName = Release;
671 | };
672 | /* End XCConfigurationList section */
673 | };
674 | rootObject = 89D84213277A218500D08BC0 /* Project object */;
675 | }
676 |
--------------------------------------------------------------------------------