├── .gitignore
├── README.md
├── android
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── kotlin
│ └── com
│ │ └── multiplatform
│ │ ├── RepoItemDelegate.kt
│ │ └── ReposActivity.kt
│ └── res
│ ├── layout
│ ├── activity_repos.xml
│ └── repo_item_layout.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── common
├── build.gradle
└── src
│ └── main
│ └── kotlin
│ └── com
│ └── multiplatform
│ ├── coroutines
│ └── Coroutines.kt
│ ├── model
│ ├── entity
│ │ ├── GithubBranch.kt
│ │ └── GithubRepo.kt
│ ├── interactor
│ │ └── ReposInteractor.kt
│ └── repository
│ │ └── ReposRepository.kt
│ └── presentation
│ ├── base
│ ├── BasePresenter.kt
│ └── BaseView.kt
│ └── repos
│ ├── ReposPresenter.kt
│ └── ReposView.kt
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── ios
├── Default-568h@2x.png
├── KMultiplatform.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── ruslankrohalev.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── KMultiplatform.xcworkspace
│ └── contents.xcworkspacedata
├── KMultiplatform
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ ├── di
│ │ └── Assembly.swift
│ ├── model
│ │ └── repository
│ │ │ ├── EntityParser.swift
│ │ │ └── ReposRepository.swift
│ └── ui
│ │ ├── ViewController.swift
│ │ └── ViewControllerAssembly.swift
├── Podfile
└── Podfile.lock
├── platform-android
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── kotlin
│ └── com
│ └── multiplatform
│ ├── coroutines
│ ├── Coroutines.kt
│ └── Deferred.kt
│ └── model
│ ├── api
│ ├── GithubApi.kt
│ └── entity
│ │ ├── ApiBranch.kt
│ │ ├── ApiCommit.kt
│ │ └── ApiRepo.kt
│ └── repository
│ └── ReposRepository.kt
├── platform-ios
├── build.gradle
└── src
│ └── main
│ └── kotlin
│ └── com
│ └── multiplatform
│ ├── coroutines
│ ├── AsyncDispatcher.kt
│ ├── ContinuationDispatcher.kt
│ ├── Coroutines.kt
│ ├── Deferred.kt
│ └── MainQueueDispatcher.kt
│ └── model
│ └── repository
│ └── ReposRepository.kt
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.ap_
3 | *.iml
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | generator/out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | .idea/
24 | !.idea/codeStyleSettings.xml
25 |
26 | .DS_Store
27 |
28 | *.trace
29 | captures/
30 | projectFilesBackup/
31 | *.xcbkptlist
32 | *.xcuserstate
33 | ios/Pods
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # kotlin_multiplatform
2 |
3 | Test project with shared kotlin code for Android and iOS.
4 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | kotlin {
6 | experimental {
7 | coroutines "enable"
8 | }
9 | }
10 |
11 | android {
12 | compileSdkVersion 27
13 | buildToolsVersion "27.0.3"
14 |
15 | defaultConfig {
16 | applicationId "com.multiplatform"
17 | minSdkVersion 21
18 | targetSdkVersion 27
19 | versionCode 1
20 | versionName "1.0"
21 |
22 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
23 |
24 | }
25 |
26 | buildTypes {
27 | release {
28 | minifyEnabled false
29 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
30 | }
31 | }
32 |
33 | sourceSets {
34 | main.java.srcDirs += 'src/main/kotlin'
35 | }
36 |
37 | packagingOptions {
38 | pickFirst 'META-INF/main.kotlin_module'
39 | }
40 |
41 | lintOptions {
42 | abortOnError false
43 | }
44 | }
45 |
46 | dependencies {
47 | androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
48 | exclude group: 'com.android.support', module: 'support-annotations'
49 | })
50 |
51 | implementation project(':platform-android')
52 |
53 | implementation 'com.android.support:appcompat-v7:27.1.0'
54 | implementation 'com.android.support.constraint:constraint-layout:1.0.2'
55 | implementation 'com.android.support:design:27.1.0'
56 | implementation "org.jetbrains.anko:anko-coroutines:0.10.1"
57 | implementation "io.reactivex.rxjava2:rxandroid:2.0.2"
58 | implementation 'com.hannesdorfmann:adapterdelegates3:3.0.1'
59 |
60 | testImplementation 'junit:junit:4.12'
61 | }
--------------------------------------------------------------------------------
/android/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/yatsinar/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/android/src/main/kotlin/com/multiplatform/RepoItemDelegate.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform
2 |
3 | import android.annotation.SuppressLint
4 | import android.support.v7.widget.RecyclerView
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import android.widget.TextView
9 | import com.example.mobiusapp.R
10 | import com.hannesdorfmann.adapterdelegates3.AdapterDelegate
11 | import com.multiplatform.model.entity.GithubRepo
12 | import kotlinx.android.synthetic.main.repo_item_layout.view.*
13 |
14 | class RepoItemDelegate : AdapterDelegate>() {
15 |
16 | override fun onCreateViewHolder(viewGroup: ViewGroup?): RecyclerView.ViewHolder
17 | = ViewHolder(LayoutInflater.from(viewGroup?.context).inflate(R.layout.repo_item_layout, viewGroup, false))
18 |
19 | @SuppressLint("SetTextI18n")
20 | override fun onBindViewHolder(list: List, position: Int, holder: RecyclerView.ViewHolder, payloads: MutableList) {
21 | val repo = list[position] as GithubRepo
22 | (holder as? ViewHolder)?.apply {
23 | repoTextView.text = repo.name
24 | branchesTextView.text = "Branches: ${repo.branches.size}"
25 | }
26 | }
27 |
28 | override fun isForViewType(list: List, position: Int): Boolean = list[position] is GithubRepo
29 |
30 | class ViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
31 | val repoTextView: TextView = view.repoTextView
32 | val branchesTextView: TextView = view.branchesTextView
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/android/src/main/kotlin/com/multiplatform/ReposActivity.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform
2 |
3 | import android.os.Bundle
4 | import android.support.v7.app.AppCompatActivity
5 | import android.support.v7.widget.LinearLayoutManager
6 | import android.view.View.GONE
7 | import android.view.View.VISIBLE
8 | import android.widget.Toast
9 | import com.example.mobiusapp.R
10 | import com.hannesdorfmann.adapterdelegates3.AdapterDelegatesManager
11 | import com.hannesdorfmann.adapterdelegates3.ListDelegationAdapter
12 | import com.multiplatform.model.entity.GithubRepo
13 | import com.multiplatform.model.interactor.ReposInteractor
14 | import com.multiplatform.model.repository.ReposRepository
15 | import com.multiplatform.presentation.repos.ReposPresenter
16 | import com.multiplatform.presentation.repos.ReposView
17 | import kotlinx.android.synthetic.main.activity_repos.*
18 | import kotlinx.coroutines.experimental.CommonPool
19 | import kotlinx.coroutines.experimental.android.UI
20 |
21 | class ReposActivity : AppCompatActivity(), ReposView {
22 |
23 | private val exchangeRepository = ReposRepository(
24 | baseUrl = "https://api.github.com/",
25 | userName = "shakurocom"
26 | )
27 |
28 | private val interactor = ReposInteractor(exchangeRepository, CommonPool)
29 |
30 | private val presenter = ReposPresenter(
31 | uiContext = UI,
32 | interactor = interactor
33 | )
34 |
35 | private val adapter by lazy {
36 | ListDelegationAdapter(AdapterDelegatesManager>().addDelegate(RepoItemDelegate()))
37 | }
38 |
39 | override fun onCreate(savedInstanceState: Bundle?) {
40 | super.onCreate(savedInstanceState)
41 | setContentView(R.layout.activity_repos)
42 |
43 | tickersRecyclerView.adapter = adapter
44 | tickersRecyclerView.layoutManager = LinearLayoutManager(this)
45 | }
46 |
47 | override fun onStart() {
48 | super.onStart()
49 | presenter.attach(this)
50 | }
51 |
52 | override fun onStop() {
53 | super.onStop()
54 | presenter.detach()
55 | }
56 |
57 | override fun showRepoList(repoList: List) {
58 | adapter.items = repoList
59 | adapter.notifyDataSetChanged()
60 | }
61 |
62 | override fun showLoading(loading: Boolean) {
63 | loadingProgress.visibility = if (loading) VISIBLE else GONE
64 | }
65 |
66 | override fun showError(errorMessage: String) {
67 | Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show()
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/android/src/main/res/layout/activity_repos.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/android/src/main/res/layout/repo_item_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
20 |
21 |
33 |
34 |
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/android/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/android/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 16dp
3 |
4 |
--------------------------------------------------------------------------------
/android/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MultiplatformApp
3 | MultiplatformApp
4 |
5 |
--------------------------------------------------------------------------------
/android/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.2.40'
5 | ext.kotlin_native_version = '0.7'
6 |
7 | repositories {
8 | google()
9 | jcenter()
10 | maven { url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies" }
11 | maven { url "https://kotlin.bintray.com/kotlinx" }
12 | }
13 |
14 | dependencies {
15 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
16 | classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$kotlin_native_version"
17 | classpath "com.android.tools.build:gradle:3.1.1"
18 | }
19 | }
20 |
21 | repositories {
22 | google()
23 | jcenter()
24 | }
25 | }
26 |
27 |
28 |
--------------------------------------------------------------------------------
/common/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'org.jetbrains.kotlin.platform.common'
2 |
3 | dependencies {
4 | implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
5 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
6 | }
7 |
8 | kotlin {
9 | experimental {
10 | coroutines "enable"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/com/multiplatform/coroutines/Coroutines.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.coroutines
2 |
3 | import kotlin.coroutines.experimental.Continuation
4 | import kotlin.coroutines.experimental.CoroutineContext
5 |
6 | expect fun async(context: CoroutineContext, block: suspend () -> T): Deferred
7 |
8 | expect fun launch(context: CoroutineContext, block: suspend () -> T)
9 |
10 | expect suspend fun withContext(context: CoroutineContext, block: suspend () -> T): T
11 |
12 | expect class Deferred {
13 | suspend fun await(): T
14 | }
15 |
16 | open class EmptyContinuation(override val context: CoroutineContext) : Continuation {
17 |
18 | companion object : EmptyContinuation(context)
19 |
20 | override fun resume(value: Any?) = Unit
21 |
22 | override fun resumeWithException(exception: Throwable) {
23 | throw exception
24 | }
25 | }
26 |
27 | open class WrappedContinuation(
28 | override val context: CoroutineContext,
29 | val continuation: Continuation
30 | ) : Continuation {
31 |
32 | companion object : WrappedContinuation(context, continuation)
33 |
34 | override fun resume(value: T) = continuation.resume(value)
35 |
36 | override fun resumeWithException(exception: Throwable) = continuation.resumeWithException(exception)
37 | }
--------------------------------------------------------------------------------
/common/src/main/kotlin/com/multiplatform/model/entity/GithubBranch.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.entity
2 |
3 | data class GithubBranch(
4 | val name: String,
5 | val commitSha: String,
6 | val commitUrl: String
7 | )
8 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/com/multiplatform/model/entity/GithubRepo.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.entity
2 |
3 | data class GithubRepo(
4 | val id: Long,
5 | val name: String,
6 | var branches: List = emptyList()
7 | )
--------------------------------------------------------------------------------
/common/src/main/kotlin/com/multiplatform/model/interactor/ReposInteractor.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.interactor
2 |
3 | import com.multiplatform.coroutines.async
4 | import com.multiplatform.model.entity.GithubRepo
5 | import com.multiplatform.model.repository.ReposRepository
6 | import kotlin.coroutines.experimental.CoroutineContext
7 |
8 | class ReposInteractor(
9 | private val repository: ReposRepository,
10 | private val context: CoroutineContext
11 | ) {
12 |
13 | suspend fun getRepos(): List {
14 | return async(context) { repository.getRepositories() }
15 | .await()
16 | .map { repo ->
17 | repo to async(context) {
18 | repository.getBranches(repo)
19 | }
20 | }
21 | .map { (repo, task) ->
22 | repo.branches = task.await()
23 | repo
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/common/src/main/kotlin/com/multiplatform/model/repository/ReposRepository.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.repository
2 |
3 | import com.multiplatform.model.entity.GithubBranch
4 | import com.multiplatform.model.entity.GithubRepo
5 |
6 | expect class ReposRepository {
7 | suspend fun getRepositories(): List
8 | suspend fun getBranches(repo: GithubRepo): List
9 | }
--------------------------------------------------------------------------------
/common/src/main/kotlin/com/multiplatform/presentation/base/BasePresenter.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.presentation.base
2 |
3 | abstract class BasePresenter {
4 |
5 | protected var view: V? = null
6 | private set
7 |
8 | fun attach(view: V) {
9 | this.view = view
10 | onViewAttached()
11 | }
12 |
13 | fun detach() {
14 | this.view = null
15 | onViewDetached()
16 | }
17 |
18 | open fun onViewAttached() {
19 |
20 | }
21 |
22 | open fun onViewDetached() {
23 |
24 | }
25 | }
26 |
27 |
28 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/com/multiplatform/presentation/base/BaseView.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.presentation.base
2 |
3 | interface BaseView
--------------------------------------------------------------------------------
/common/src/main/kotlin/com/multiplatform/presentation/repos/ReposPresenter.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.presentation.repos
2 |
3 | import com.multiplatform.model.interactor.ReposInteractor
4 | import kotlin.coroutines.experimental.CoroutineContext
5 | import com.multiplatform.presentation.base.BasePresenter
6 | import com.multiplatform.coroutines.launch
7 |
8 | class ReposPresenter(
9 | private val uiContext: CoroutineContext,
10 | private val interactor: ReposInteractor
11 | ) : BasePresenter() {
12 |
13 | override fun onViewAttached() {
14 | super.onViewAttached()
15 | refresh()
16 | }
17 |
18 | fun refresh() {
19 | launch(uiContext) {
20 | view?.showLoading(true)
21 | try {
22 | val repoList = interactor.getRepos()
23 | view?.showRepoList(repoList)
24 | } catch (e: Throwable) {
25 | view?.showError(e.message ?: "Can't load repositories")
26 | }
27 | view?.showLoading(false)
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/com/multiplatform/presentation/repos/ReposView.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.presentation.repos
2 |
3 | import com.multiplatform.model.entity.GithubRepo
4 | import com.multiplatform.presentation.base.BaseView
5 |
6 | interface ReposView: BaseView {
7 | fun showRepoList(repoList: List)
8 | fun showLoading(loading: Boolean)
9 | fun showError(errorMessage: String)
10 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 | INCLUDE_ANDROID=true
19 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Mar 26 12:40:18 MSK 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn ( ) {
37 | echo "$*"
38 | }
39 |
40 | die ( ) {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save ( ) {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/ios/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shakurocom/kotlin_multiplatform/0478edebe2502da23d6c247d88aca2ec199adde2/ios/Default-568h@2x.png
--------------------------------------------------------------------------------
/ios/KMultiplatform.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 3447DC0C28E3C33630E642AA /* Pods_multi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24955CED575CAF9EAC74D8D4 /* Pods_multi.framework */; };
11 | 4F7113DF20B2B81E006805C8 /* EntityParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F7113DE20B2B81E006805C8 /* EntityParser.swift */; };
12 | 4F8BB90C20AEF04100C089E8 /* KMulti.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F8BB90A20AEF02F00C089E8 /* KMulti.framework */; };
13 | 4F8BB90D20AEF04100C089E8 /* KMulti.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4F8BB90A20AEF02F00C089E8 /* KMulti.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
14 | 4F8BB91020AEFA9A00C089E8 /* Assembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F8BB90F20AEFA9A00C089E8 /* Assembly.swift */; };
15 | 4F8BB91620AF058400C089E8 /* ViewControllerAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F8BB91520AF058400C089E8 /* ViewControllerAssembly.swift */; };
16 | 4FB4F59E20AEC0E2008639F4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FB4F59D20AEC0E2008639F4 /* AppDelegate.swift */; };
17 | 4FB4F5A020AEC0E2008639F4 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FB4F59F20AEC0E2008639F4 /* ViewController.swift */; };
18 | 4FB4F5A320AEC0E2008639F4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4FB4F5A120AEC0E2008639F4 /* Main.storyboard */; };
19 | 4FB4F5A520AEC0E2008639F4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4FB4F5A420AEC0E2008639F4 /* Assets.xcassets */; };
20 | 4FB4F5A820AEC0E2008639F4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4FB4F5A620AEC0E2008639F4 /* LaunchScreen.storyboard */; };
21 | 4FB4F5B020AEC257008639F4 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4FB4F5AF20AEC257008639F4 /* Default-568h@2x.png */; };
22 | 4FB4F5B420AECB48008639F4 /* ReposRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FB4F5B320AECB48008639F4 /* ReposRepository.swift */; };
23 | /* End PBXBuildFile section */
24 |
25 | /* Begin PBXCopyFilesBuildPhase section */
26 | 4FB4F5BC20AECE0C008639F4 /* Embed Frameworks */ = {
27 | isa = PBXCopyFilesBuildPhase;
28 | buildActionMask = 2147483647;
29 | dstPath = "";
30 | dstSubfolderSpec = 10;
31 | files = (
32 | 4F8BB90D20AEF04100C089E8 /* KMulti.framework in Embed Frameworks */,
33 | );
34 | name = "Embed Frameworks";
35 | runOnlyForDeploymentPostprocessing = 0;
36 | };
37 | /* End PBXCopyFilesBuildPhase section */
38 |
39 | /* Begin PBXFileReference section */
40 | 24955CED575CAF9EAC74D8D4 /* Pods_multi.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_multi.framework; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 3FA2161C59C5A313702DECFA /* Pods-multi.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-multi.debug.xcconfig"; path = "Pods/Target Support Files/Pods-multi/Pods-multi.debug.xcconfig"; sourceTree = ""; };
42 | 4F7113DE20B2B81E006805C8 /* EntityParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntityParser.swift; sourceTree = ""; };
43 | 4F8BB90A20AEF02F00C089E8 /* KMulti.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = KMulti.framework; path = "../platform-ios/build/konan/bin/ios_x64/KMulti.framework"; sourceTree = ""; };
44 | 4F8BB90F20AEFA9A00C089E8 /* Assembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Assembly.swift; sourceTree = ""; };
45 | 4F8BB91520AF058400C089E8 /* ViewControllerAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewControllerAssembly.swift; sourceTree = ""; };
46 | 4FB4F59A20AEC0E2008639F4 /* multi.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = multi.app; sourceTree = BUILT_PRODUCTS_DIR; };
47 | 4FB4F59D20AEC0E2008639F4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
48 | 4FB4F59F20AEC0E2008639F4 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
49 | 4FB4F5A220AEC0E2008639F4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
50 | 4FB4F5A420AEC0E2008639F4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
51 | 4FB4F5A720AEC0E2008639F4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
52 | 4FB4F5A920AEC0E2008639F4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
53 | 4FB4F5AF20AEC257008639F4 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; };
54 | 4FB4F5B320AECB48008639F4 /* ReposRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReposRepository.swift; sourceTree = ""; };
55 | EEE778939384AA94366B4043 /* Pods-multi.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-multi.release.xcconfig"; path = "Pods/Target Support Files/Pods-multi/Pods-multi.release.xcconfig"; sourceTree = ""; };
56 | /* End PBXFileReference section */
57 |
58 | /* Begin PBXFrameworksBuildPhase section */
59 | 4FB4F59720AEC0E2008639F4 /* Frameworks */ = {
60 | isa = PBXFrameworksBuildPhase;
61 | buildActionMask = 2147483647;
62 | files = (
63 | 4F8BB90C20AEF04100C089E8 /* KMulti.framework in Frameworks */,
64 | 3447DC0C28E3C33630E642AA /* Pods_multi.framework in Frameworks */,
65 | );
66 | runOnlyForDeploymentPostprocessing = 0;
67 | };
68 | /* End PBXFrameworksBuildPhase section */
69 |
70 | /* Begin PBXGroup section */
71 | 2390973FE6D50ED891DE2CC8 /* Frameworks */ = {
72 | isa = PBXGroup;
73 | children = (
74 | 4F8BB90A20AEF02F00C089E8 /* KMulti.framework */,
75 | 24955CED575CAF9EAC74D8D4 /* Pods_multi.framework */,
76 | );
77 | name = Frameworks;
78 | sourceTree = "";
79 | };
80 | 4F8BB90E20AEFA7400C089E8 /* di */ = {
81 | isa = PBXGroup;
82 | children = (
83 | 4F8BB90F20AEFA9A00C089E8 /* Assembly.swift */,
84 | );
85 | path = di;
86 | sourceTree = "";
87 | };
88 | 4F8BB91420AF03DC00C089E8 /* ui */ = {
89 | isa = PBXGroup;
90 | children = (
91 | 4FB4F59F20AEC0E2008639F4 /* ViewController.swift */,
92 | 4F8BB91520AF058400C089E8 /* ViewControllerAssembly.swift */,
93 | );
94 | path = ui;
95 | sourceTree = "";
96 | };
97 | 4FB4F59120AEC0E2008639F4 = {
98 | isa = PBXGroup;
99 | children = (
100 | 4FB4F5AF20AEC257008639F4 /* Default-568h@2x.png */,
101 | 4FB4F59C20AEC0E2008639F4 /* KMultiplatform */,
102 | 4FB4F59B20AEC0E2008639F4 /* Products */,
103 | FD547A74CB2FB3FFC2ADECD9 /* Pods */,
104 | 2390973FE6D50ED891DE2CC8 /* Frameworks */,
105 | );
106 | sourceTree = "";
107 | };
108 | 4FB4F59B20AEC0E2008639F4 /* Products */ = {
109 | isa = PBXGroup;
110 | children = (
111 | 4FB4F59A20AEC0E2008639F4 /* multi.app */,
112 | );
113 | name = Products;
114 | sourceTree = "";
115 | };
116 | 4FB4F59C20AEC0E2008639F4 /* KMultiplatform */ = {
117 | isa = PBXGroup;
118 | children = (
119 | 4F8BB90E20AEFA7400C089E8 /* di */,
120 | 4FB4F5B120AECAFC008639F4 /* model */,
121 | 4F8BB91420AF03DC00C089E8 /* ui */,
122 | 4FB4F59D20AEC0E2008639F4 /* AppDelegate.swift */,
123 | 4FB4F5A120AEC0E2008639F4 /* Main.storyboard */,
124 | 4FB4F5A420AEC0E2008639F4 /* Assets.xcassets */,
125 | 4FB4F5A620AEC0E2008639F4 /* LaunchScreen.storyboard */,
126 | 4FB4F5A920AEC0E2008639F4 /* Info.plist */,
127 | );
128 | path = KMultiplatform;
129 | sourceTree = "";
130 | };
131 | 4FB4F5B120AECAFC008639F4 /* model */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 4FB4F5B220AECB17008639F4 /* repository */,
135 | );
136 | path = model;
137 | sourceTree = "";
138 | };
139 | 4FB4F5B220AECB17008639F4 /* repository */ = {
140 | isa = PBXGroup;
141 | children = (
142 | 4F7113DE20B2B81E006805C8 /* EntityParser.swift */,
143 | 4FB4F5B320AECB48008639F4 /* ReposRepository.swift */,
144 | );
145 | path = repository;
146 | sourceTree = "";
147 | };
148 | FD547A74CB2FB3FFC2ADECD9 /* Pods */ = {
149 | isa = PBXGroup;
150 | children = (
151 | 3FA2161C59C5A313702DECFA /* Pods-multi.debug.xcconfig */,
152 | EEE778939384AA94366B4043 /* Pods-multi.release.xcconfig */,
153 | );
154 | name = Pods;
155 | sourceTree = "";
156 | };
157 | /* End PBXGroup section */
158 |
159 | /* Begin PBXNativeTarget section */
160 | 4FB4F59920AEC0E2008639F4 /* multi */ = {
161 | isa = PBXNativeTarget;
162 | buildConfigurationList = 4FB4F5AC20AEC0E2008639F4 /* Build configuration list for PBXNativeTarget "multi" */;
163 | buildPhases = (
164 | AB2854ACF938DB9D6F69E755 /* [CP] Check Pods Manifest.lock */,
165 | 4FB4F59620AEC0E2008639F4 /* Sources */,
166 | 4FB4F59720AEC0E2008639F4 /* Frameworks */,
167 | 4FB4F59820AEC0E2008639F4 /* Resources */,
168 | D889EFC5D95316FB0EFF6944 /* [CP] Embed Pods Frameworks */,
169 | DE5D3170304B6DFE7DDB969D /* [CP] Copy Pods Resources */,
170 | 4FB4F5BC20AECE0C008639F4 /* Embed Frameworks */,
171 | );
172 | buildRules = (
173 | );
174 | dependencies = (
175 | );
176 | name = multi;
177 | productName = KMultiplatform;
178 | productReference = 4FB4F59A20AEC0E2008639F4 /* multi.app */;
179 | productType = "com.apple.product-type.application";
180 | };
181 | /* End PBXNativeTarget section */
182 |
183 | /* Begin PBXProject section */
184 | 4FB4F59220AEC0E2008639F4 /* Project object */ = {
185 | isa = PBXProject;
186 | attributes = {
187 | LastSwiftUpdateCheck = 0920;
188 | LastUpgradeCheck = 0920;
189 | ORGANIZATIONNAME = "Ruslan Krohalev";
190 | TargetAttributes = {
191 | 4FB4F59920AEC0E2008639F4 = {
192 | CreatedOnToolsVersion = 9.2;
193 | ProvisioningStyle = Automatic;
194 | };
195 | };
196 | };
197 | buildConfigurationList = 4FB4F59520AEC0E2008639F4 /* Build configuration list for PBXProject "KMultiplatform" */;
198 | compatibilityVersion = "Xcode 8.0";
199 | developmentRegion = en;
200 | hasScannedForEncodings = 0;
201 | knownRegions = (
202 | en,
203 | Base,
204 | );
205 | mainGroup = 4FB4F59120AEC0E2008639F4;
206 | productRefGroup = 4FB4F59B20AEC0E2008639F4 /* Products */;
207 | projectDirPath = "";
208 | projectRoot = "";
209 | targets = (
210 | 4FB4F59920AEC0E2008639F4 /* multi */,
211 | );
212 | };
213 | /* End PBXProject section */
214 |
215 | /* Begin PBXResourcesBuildPhase section */
216 | 4FB4F59820AEC0E2008639F4 /* Resources */ = {
217 | isa = PBXResourcesBuildPhase;
218 | buildActionMask = 2147483647;
219 | files = (
220 | 4FB4F5A820AEC0E2008639F4 /* LaunchScreen.storyboard in Resources */,
221 | 4FB4F5B020AEC257008639F4 /* Default-568h@2x.png in Resources */,
222 | 4FB4F5A520AEC0E2008639F4 /* Assets.xcassets in Resources */,
223 | 4FB4F5A320AEC0E2008639F4 /* Main.storyboard in Resources */,
224 | );
225 | runOnlyForDeploymentPostprocessing = 0;
226 | };
227 | /* End PBXResourcesBuildPhase section */
228 |
229 | /* Begin PBXShellScriptBuildPhase section */
230 | AB2854ACF938DB9D6F69E755 /* [CP] Check Pods Manifest.lock */ = {
231 | isa = PBXShellScriptBuildPhase;
232 | buildActionMask = 2147483647;
233 | files = (
234 | );
235 | inputPaths = (
236 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
237 | "${PODS_ROOT}/Manifest.lock",
238 | );
239 | name = "[CP] Check Pods Manifest.lock";
240 | outputPaths = (
241 | "$(DERIVED_FILE_DIR)/Pods-multi-checkManifestLockResult.txt",
242 | );
243 | runOnlyForDeploymentPostprocessing = 0;
244 | shellPath = /bin/sh;
245 | 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";
246 | showEnvVarsInLog = 0;
247 | };
248 | D889EFC5D95316FB0EFF6944 /* [CP] Embed Pods Frameworks */ = {
249 | isa = PBXShellScriptBuildPhase;
250 | buildActionMask = 2147483647;
251 | files = (
252 | );
253 | inputPaths = (
254 | "${SRCROOT}/Pods/Target Support Files/Pods-multi/Pods-multi-frameworks.sh",
255 | "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework",
256 | "${BUILT_PRODUCTS_DIR}/EasyDi/EasyDi.framework",
257 | "${BUILT_PRODUCTS_DIR}/SwiftyJSON/SwiftyJSON.framework",
258 | );
259 | name = "[CP] Embed Pods Frameworks";
260 | outputPaths = (
261 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework",
262 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/EasyDi.framework",
263 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyJSON.framework",
264 | );
265 | runOnlyForDeploymentPostprocessing = 0;
266 | shellPath = /bin/sh;
267 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-multi/Pods-multi-frameworks.sh\"\n";
268 | showEnvVarsInLog = 0;
269 | };
270 | DE5D3170304B6DFE7DDB969D /* [CP] Copy Pods Resources */ = {
271 | isa = PBXShellScriptBuildPhase;
272 | buildActionMask = 2147483647;
273 | files = (
274 | );
275 | inputPaths = (
276 | );
277 | name = "[CP] Copy Pods Resources";
278 | outputPaths = (
279 | );
280 | runOnlyForDeploymentPostprocessing = 0;
281 | shellPath = /bin/sh;
282 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-multi/Pods-multi-resources.sh\"\n";
283 | showEnvVarsInLog = 0;
284 | };
285 | /* End PBXShellScriptBuildPhase section */
286 |
287 | /* Begin PBXSourcesBuildPhase section */
288 | 4FB4F59620AEC0E2008639F4 /* Sources */ = {
289 | isa = PBXSourcesBuildPhase;
290 | buildActionMask = 2147483647;
291 | files = (
292 | 4FB4F5A020AEC0E2008639F4 /* ViewController.swift in Sources */,
293 | 4F7113DF20B2B81E006805C8 /* EntityParser.swift in Sources */,
294 | 4F8BB91020AEFA9A00C089E8 /* Assembly.swift in Sources */,
295 | 4FB4F5B420AECB48008639F4 /* ReposRepository.swift in Sources */,
296 | 4FB4F59E20AEC0E2008639F4 /* AppDelegate.swift in Sources */,
297 | 4F8BB91620AF058400C089E8 /* ViewControllerAssembly.swift in Sources */,
298 | );
299 | runOnlyForDeploymentPostprocessing = 0;
300 | };
301 | /* End PBXSourcesBuildPhase section */
302 |
303 | /* Begin PBXVariantGroup section */
304 | 4FB4F5A120AEC0E2008639F4 /* Main.storyboard */ = {
305 | isa = PBXVariantGroup;
306 | children = (
307 | 4FB4F5A220AEC0E2008639F4 /* Base */,
308 | );
309 | name = Main.storyboard;
310 | sourceTree = "";
311 | };
312 | 4FB4F5A620AEC0E2008639F4 /* LaunchScreen.storyboard */ = {
313 | isa = PBXVariantGroup;
314 | children = (
315 | 4FB4F5A720AEC0E2008639F4 /* Base */,
316 | );
317 | name = LaunchScreen.storyboard;
318 | sourceTree = "";
319 | };
320 | /* End PBXVariantGroup section */
321 |
322 | /* Begin XCBuildConfiguration section */
323 | 4FB4F5AA20AEC0E2008639F4 /* Debug */ = {
324 | isa = XCBuildConfiguration;
325 | buildSettings = {
326 | ALWAYS_SEARCH_USER_PATHS = NO;
327 | CLANG_ANALYZER_NONNULL = YES;
328 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
329 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
330 | CLANG_CXX_LIBRARY = "libc++";
331 | CLANG_ENABLE_MODULES = YES;
332 | CLANG_ENABLE_OBJC_ARC = YES;
333 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
334 | CLANG_WARN_BOOL_CONVERSION = YES;
335 | CLANG_WARN_COMMA = YES;
336 | CLANG_WARN_CONSTANT_CONVERSION = YES;
337 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
338 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
339 | CLANG_WARN_EMPTY_BODY = YES;
340 | CLANG_WARN_ENUM_CONVERSION = YES;
341 | CLANG_WARN_INFINITE_RECURSION = YES;
342 | CLANG_WARN_INT_CONVERSION = YES;
343 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
344 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
345 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
346 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
347 | CLANG_WARN_STRICT_PROTOTYPES = YES;
348 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
349 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
350 | CLANG_WARN_UNREACHABLE_CODE = YES;
351 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
352 | CODE_SIGN_IDENTITY = "iPhone Developer";
353 | COPY_PHASE_STRIP = NO;
354 | DEBUG_INFORMATION_FORMAT = dwarf;
355 | ENABLE_STRICT_OBJC_MSGSEND = YES;
356 | ENABLE_TESTABILITY = YES;
357 | GCC_C_LANGUAGE_STANDARD = gnu11;
358 | GCC_DYNAMIC_NO_PIC = NO;
359 | GCC_NO_COMMON_BLOCKS = YES;
360 | GCC_OPTIMIZATION_LEVEL = 0;
361 | GCC_PREPROCESSOR_DEFINITIONS = (
362 | "DEBUG=1",
363 | "$(inherited)",
364 | );
365 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
366 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
367 | GCC_WARN_UNDECLARED_SELECTOR = YES;
368 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
369 | GCC_WARN_UNUSED_FUNCTION = YES;
370 | GCC_WARN_UNUSED_VARIABLE = YES;
371 | IPHONEOS_DEPLOYMENT_TARGET = 11.2;
372 | MTL_ENABLE_DEBUG_INFO = YES;
373 | ONLY_ACTIVE_ARCH = YES;
374 | SDKROOT = iphoneos;
375 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
376 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
377 | };
378 | name = Debug;
379 | };
380 | 4FB4F5AB20AEC0E2008639F4 /* Release */ = {
381 | isa = XCBuildConfiguration;
382 | buildSettings = {
383 | ALWAYS_SEARCH_USER_PATHS = NO;
384 | CLANG_ANALYZER_NONNULL = YES;
385 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
386 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
387 | CLANG_CXX_LIBRARY = "libc++";
388 | CLANG_ENABLE_MODULES = YES;
389 | CLANG_ENABLE_OBJC_ARC = YES;
390 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
391 | CLANG_WARN_BOOL_CONVERSION = YES;
392 | CLANG_WARN_COMMA = YES;
393 | CLANG_WARN_CONSTANT_CONVERSION = YES;
394 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
395 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
396 | CLANG_WARN_EMPTY_BODY = YES;
397 | CLANG_WARN_ENUM_CONVERSION = YES;
398 | CLANG_WARN_INFINITE_RECURSION = YES;
399 | CLANG_WARN_INT_CONVERSION = YES;
400 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
401 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
402 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
403 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
404 | CLANG_WARN_STRICT_PROTOTYPES = YES;
405 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
406 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
407 | CLANG_WARN_UNREACHABLE_CODE = YES;
408 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
409 | CODE_SIGN_IDENTITY = "iPhone Developer";
410 | COPY_PHASE_STRIP = NO;
411 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
412 | ENABLE_NS_ASSERTIONS = NO;
413 | ENABLE_STRICT_OBJC_MSGSEND = YES;
414 | GCC_C_LANGUAGE_STANDARD = gnu11;
415 | GCC_NO_COMMON_BLOCKS = YES;
416 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
417 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
418 | GCC_WARN_UNDECLARED_SELECTOR = YES;
419 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
420 | GCC_WARN_UNUSED_FUNCTION = YES;
421 | GCC_WARN_UNUSED_VARIABLE = YES;
422 | IPHONEOS_DEPLOYMENT_TARGET = 11.2;
423 | MTL_ENABLE_DEBUG_INFO = NO;
424 | SDKROOT = iphoneos;
425 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
426 | VALIDATE_PRODUCT = YES;
427 | };
428 | name = Release;
429 | };
430 | 4FB4F5AD20AEC0E2008639F4 /* Debug */ = {
431 | isa = XCBuildConfiguration;
432 | baseConfigurationReference = 3FA2161C59C5A313702DECFA /* Pods-multi.debug.xcconfig */;
433 | buildSettings = {
434 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
435 | CODE_SIGN_STYLE = Automatic;
436 | DEVELOPMENT_TEAM = 9RQRQSKXB8;
437 | FRAMEWORK_SEARCH_PATHS = (
438 | "$(PROJECT_DIR)/../platform-ios/build/konan/bin/ios_x64",
439 | "$(inherited)",
440 | "\"${PODS_CONFIGURATION_BUILD_DIR}/Alamofire\"",
441 | "\"${PODS_CONFIGURATION_BUILD_DIR}/EasyDi\"",
442 | "\"${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON\"",
443 | );
444 | INFOPLIST_FILE = KMultiplatform/Info.plist;
445 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
446 | PRODUCT_BUNDLE_IDENTIFIER = com.shakuro.KMultiplatform;
447 | PRODUCT_NAME = "$(TARGET_NAME)";
448 | SWIFT_VERSION = 4.0;
449 | TARGETED_DEVICE_FAMILY = "1,2";
450 | };
451 | name = Debug;
452 | };
453 | 4FB4F5AE20AEC0E2008639F4 /* Release */ = {
454 | isa = XCBuildConfiguration;
455 | baseConfigurationReference = EEE778939384AA94366B4043 /* Pods-multi.release.xcconfig */;
456 | buildSettings = {
457 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
458 | CODE_SIGN_STYLE = Automatic;
459 | DEVELOPMENT_TEAM = 9RQRQSKXB8;
460 | FRAMEWORK_SEARCH_PATHS = (
461 | "$(PROJECT_DIR)/../platform-ios/build/konan/bin/ios_x64",
462 | "$(inherited)",
463 | "\"${PODS_CONFIGURATION_BUILD_DIR}/Alamofire\"",
464 | "\"${PODS_CONFIGURATION_BUILD_DIR}/EasyDi\"",
465 | "\"${PODS_CONFIGURATION_BUILD_DIR}/SwiftyJSON\"",
466 | );
467 | INFOPLIST_FILE = KMultiplatform/Info.plist;
468 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
469 | PRODUCT_BUNDLE_IDENTIFIER = com.shakuro.KMultiplatform;
470 | PRODUCT_NAME = "$(TARGET_NAME)";
471 | SWIFT_VERSION = 4.0;
472 | TARGETED_DEVICE_FAMILY = "1,2";
473 | };
474 | name = Release;
475 | };
476 | /* End XCBuildConfiguration section */
477 |
478 | /* Begin XCConfigurationList section */
479 | 4FB4F59520AEC0E2008639F4 /* Build configuration list for PBXProject "KMultiplatform" */ = {
480 | isa = XCConfigurationList;
481 | buildConfigurations = (
482 | 4FB4F5AA20AEC0E2008639F4 /* Debug */,
483 | 4FB4F5AB20AEC0E2008639F4 /* Release */,
484 | );
485 | defaultConfigurationIsVisible = 0;
486 | defaultConfigurationName = Release;
487 | };
488 | 4FB4F5AC20AEC0E2008639F4 /* Build configuration list for PBXNativeTarget "multi" */ = {
489 | isa = XCConfigurationList;
490 | buildConfigurations = (
491 | 4FB4F5AD20AEC0E2008639F4 /* Debug */,
492 | 4FB4F5AE20AEC0E2008639F4 /* Release */,
493 | );
494 | defaultConfigurationIsVisible = 0;
495 | defaultConfigurationName = Release;
496 | };
497 | /* End XCConfigurationList section */
498 | };
499 | rootObject = 4FB4F59220AEC0E2008639F4 /* Project object */;
500 | }
501 |
--------------------------------------------------------------------------------
/ios/KMultiplatform.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/KMultiplatform.xcodeproj/xcuserdata/ruslankrohalev.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | KMultiplatform.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 | multi.xcscheme
13 |
14 | orderHint
15 | 4
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ios/KMultiplatform.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/KMultiplatform/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // KMultiplatform
4 | //
5 | // Created by Ruslan Krohalev on 18/05/2018.
6 | // Copyright © 2018 Ruslan Krohalev. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/ios/KMultiplatform/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/ios/KMultiplatform/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/ios/KMultiplatform/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
35 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/ios/KMultiplatform/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 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/KMultiplatform/di/Assembly.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import EasyDi
3 | import KMulti
4 |
5 | class ServiceAssembly: Assembly {
6 |
7 | var apiBaseUrl: URL! = URL(string: "https://api.github.com")
8 |
9 | var githubUser = "shakurocom"
10 |
11 | var reposParser: GithubReposParser {
12 | return define(init: GithubReposParser())
13 | }
14 |
15 | var branchesParser: GithubBranchesParser {
16 | return define(init: GithubBranchesParser())
17 | }
18 |
19 | var reposRepository: ReposRepository {
20 | return define(scope: .lazySingleton, init: ReposRepository(
21 | baseUrl: self.apiBaseUrl,
22 | githubUser: self.githubUser,
23 | reposParser: self.reposParser,
24 | branchesParser: self.branchesParser
25 | ))
26 | }
27 |
28 | var reposInteractor: KMultiReposInteractor {
29 | return define(init: KMultiReposInteractor(
30 | repository: self.reposRepository,
31 | context: KMultiAsyncDispatcher()
32 | ))
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ios/KMultiplatform/model/repository/EntityParser.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import Alamofire
3 | import SwiftyJSON
4 | import KMulti
5 |
6 | protocol EntityParser {
7 | associatedtype T
8 |
9 | func parse(response: DataResponse) -> T?
10 | }
11 |
12 | class GithubReposParser: EntityParser {
13 |
14 | typealias T = [KMultiGithubRepo]
15 |
16 | func parse(response: DataResponse) -> [KMultiGithubRepo]? {
17 | if let result = response.result.value {
18 | let jsonArray = JSON(result).arrayValue
19 | return jsonArray.map({json -> KMultiGithubRepo in
20 | return KMultiGithubRepo(
21 | id: json["id"].int64Value,
22 | name: json["name"].stringValue,
23 | branches: []
24 | )
25 | })
26 | } else {
27 | return nil
28 | }
29 | }
30 | }
31 |
32 | class GithubBranchesParser: EntityParser {
33 |
34 | typealias T = [KMultiGithubBranch]
35 |
36 | func parse(response: DataResponse) -> [KMultiGithubBranch]? {
37 | if let result = response.result.value {
38 | let jsonArray = JSON(result).arrayValue
39 | return jsonArray.map({json -> KMultiGithubBranch in
40 | let commitJson = json["commit"].dictionaryValue
41 | return KMultiGithubBranch(
42 | name: json["name"].stringValue,
43 | commitSha: (commitJson["sha"]?.stringValue ?? ""),
44 | commitUrl: (commitJson["url"]?.stringValue ?? "")
45 | )
46 | })
47 | } else {
48 | return nil
49 | }
50 | }
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/ios/KMultiplatform/model/repository/ReposRepository.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | import Foundation
4 | import Alamofire
5 | import KMulti
6 |
7 | class ReposRepository: KMultiReposRepository {
8 |
9 | let baseUrl: URL
10 | let githubUser: String
11 | let reposParser: GithubReposParser
12 | let branchesParser: GithubBranchesParser
13 |
14 | init(baseUrl: URL, githubUser: String, reposParser: GithubReposParser, branchesParser: GithubBranchesParser) {
15 | self.baseUrl = baseUrl
16 | self.githubUser = githubUser
17 | self.reposParser = reposParser
18 | self.branchesParser = branchesParser
19 | }
20 |
21 | override func getRepositories(callback: KMultiStdlibContinuation) {
22 | let url = baseUrl.appendingPathComponent("users/\(githubUser)/repos")
23 | Alamofire.request(url)
24 | // .debugLog()
25 | .responseJSON { response in
26 | if let result = self.reposParser.parse(response: response) {
27 | callback.resume(value: result)
28 | } else {
29 | callback.resumeWithException(exception: KMultiStdlibThrowable(message: "Can't parse github repositories"))
30 | }
31 | }
32 | }
33 |
34 | override func getBranches(repo: KMultiGithubRepo, callback: KMultiStdlibContinuation) {
35 | let url = baseUrl.appendingPathComponent("repos/\(githubUser)/\(repo.name)/branches")
36 | Alamofire.request(url)
37 | // .debugLog()
38 | .responseJSON { response in
39 | if let result = self.branchesParser.parse(response: response) {
40 | callback.resume(value: result)
41 | } else {
42 | callback.resumeWithException(exception: KMultiStdlibThrowable(message: "Can't parse github branches"))
43 | }
44 | }
45 | }
46 | }
47 |
48 | fileprivate extension Request {
49 | func debugLog() -> Self {
50 | #if DEBUG
51 | debugPrint(self)
52 | #endif
53 | return self
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/ios/KMultiplatform/ui/ViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import KMulti
3 |
4 | class ViewController: UITableViewController, KMultiReposView {
5 |
6 | var presenter: KMultiReposPresenter!
7 | var items = [KMultiGithubRepo]()
8 |
9 | override func awakeFromNib() {
10 | super.awakeFromNib()
11 | ViewControllerAssembly.instance().inject(into: self)
12 | }
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 | tableView.separatorStyle = .none
17 | }
18 |
19 | override func viewWillAppear(_ animated: Bool) {
20 | super.viewWillAppear(animated)
21 | presenter.attach(view: self)
22 | }
23 |
24 | override func viewDidDisappear(_ animated: Bool) {
25 | super.viewDidDisappear(animated)
26 | presenter.detach()
27 | }
28 |
29 | func showRepoList(repoList: [KMultiGithubRepo]) {
30 | items.removeAll()
31 | items.append(contentsOf: repoList)
32 | tableView.reloadData()
33 | }
34 |
35 | func showLoading(loading: Bool) {
36 | if (loading) {
37 | refreshControl?.beginRefreshing()
38 | refreshControl?.isHidden = false
39 | } else {
40 | refreshControl?.endRefreshing()
41 | }
42 | }
43 |
44 | func showError(errorMessage: String) {
45 | // TODO
46 | }
47 |
48 | @IBAction func refresh(refreshControl: UIRefreshControl) {
49 | presenter.refresh()
50 | }
51 |
52 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
53 | return items.count
54 | }
55 |
56 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
57 | let cell = tableView.dequeueReusableCell(withIdentifier: "TitleCell", for: indexPath)
58 | let repo = items[indexPath.item]
59 | cell.textLabel?.text = repo.name
60 | cell.detailTextLabel?.text = "Branches: \(repo.branches.count)"
61 | return cell
62 | }
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/ios/KMultiplatform/ui/ViewControllerAssembly.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import EasyDi
3 | import KMulti
4 |
5 | class ViewControllerAssembly: Assembly {
6 |
7 | lazy var serviceAssembly: ServiceAssembly = self.context.assembly()
8 |
9 | func inject(into viewController: ViewController) {
10 | defineInjection(into: viewController) {
11 | $0.presenter = KMultiReposPresenter(
12 | uiContext: KMultiMainQueueDispatcher(),
13 | interactor: self.serviceAssembly.reposInteractor
14 | )
15 | return $0
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 | platform :ios, '10.0'
3 | use_frameworks!
4 |
5 | target 'multi' do
6 | inherit! :search_paths
7 | pod 'Alamofire', '~> 4.7'
8 | pod 'SwiftyJSON'
9 | pod 'EasyDi'
10 | end
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Alamofire (4.7.2)
3 | - EasyDi (1.4.0)
4 | - SwiftyJSON (4.1.0)
5 |
6 | DEPENDENCIES:
7 | - Alamofire (~> 4.7)
8 | - EasyDi
9 | - SwiftyJSON
10 |
11 | SPEC CHECKSUMS:
12 | Alamofire: e4fa87002c137ba2d8d634d2c51fabcda0d5c223
13 | EasyDi: 84cfe04e906c0f463b1b1d76ed4be3db446f9702
14 | SwiftyJSON: c29297daf073d2aa016295d5809cdd68045c39b3
15 |
16 | PODFILE CHECKSUM: 35949ac918a9e6e3807dea4c347cad4112c82225
17 |
18 | COCOAPODS: 1.4.0
19 |
--------------------------------------------------------------------------------
/platform-android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-platform-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | kotlin {
6 | experimental {
7 | coroutines "enable"
8 | }
9 | }
10 |
11 | android {
12 | compileSdkVersion 27
13 | buildToolsVersion "27.0.3"
14 |
15 | defaultConfig {
16 | minSdkVersion 21
17 | targetSdkVersion 27
18 | versionCode 1
19 | versionName "1.0"
20 | }
21 | buildTypes {
22 | release
23 | }
24 | sourceSets {
25 | main.java.srcDirs += 'src/main/kotlin'
26 | }
27 | }
28 |
29 | dependencies {
30 | expectedBy project(":common")
31 |
32 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
33 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.2"
34 | implementation group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.1.11'
35 | implementation 'com.squareup.retrofit2:retrofit:2.4.0'
36 | implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-experimental-adapter:1.0.0'
37 | implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
38 | implementation 'com.google.code.gson:gson:2.8.2'
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/platform-android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/platform-android/src/main/kotlin/com/multiplatform/coroutines/Coroutines.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.coroutines
2 |
3 | import kotlinx.coroutines.experimental.async
4 | import kotlin.coroutines.experimental.CoroutineContext
5 |
6 | actual fun async(context: CoroutineContext, block: suspend () -> T): Deferred {
7 | return Deferred(async {
8 | kotlinx.coroutines.experimental.withContext(context, block = block)
9 | })
10 | }
11 |
12 | actual fun launch(context: CoroutineContext, block: suspend () -> T) {
13 | kotlinx.coroutines.experimental.launch(context) {
14 | block()
15 | }
16 | }
17 |
18 | actual suspend fun withContext(context: CoroutineContext, block: suspend () -> T): T {
19 | return kotlinx.coroutines.experimental.withContext(context = context, block = block)
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/platform-android/src/main/kotlin/com/multiplatform/coroutines/Deferred.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.coroutines
2 |
3 | import kotlinx.coroutines.experimental.Deferred
4 |
5 | actual class Deferred(
6 | private val wrappedDeferred: Deferred
7 | ) {
8 |
9 | actual suspend fun await(): T {
10 | return wrappedDeferred.await()
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/platform-android/src/main/kotlin/com/multiplatform/model/api/GithubApi.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.api
2 |
3 | import com.multiplatform.model.api.entity.ApiBranch
4 | import com.multiplatform.model.api.entity.ApiRepo
5 | import kotlinx.coroutines.experimental.Deferred
6 | import retrofit2.http.GET
7 | import retrofit2.http.Path
8 |
9 | interface GithubApi {
10 |
11 | @GET("users/{userName}/repos")
12 | fun getRepositories(
13 | @Path("userName") userName: String
14 | ): Deferred>
15 |
16 | @GET("repos/{userName}/{repoName}/branches")
17 | fun getBranches(
18 | @Path("userName") userName: String,
19 | @Path("repoName") repoName: String
20 | ): Deferred>
21 | }
--------------------------------------------------------------------------------
/platform-android/src/main/kotlin/com/multiplatform/model/api/entity/ApiBranch.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.api.entity
2 |
3 | import com.multiplatform.model.entity.GithubBranch
4 |
5 | data class ApiBranch(
6 | val name: String,
7 | val commit: ApiCommit
8 | ) {
9 | fun toGithubBranch(): GithubBranch = GithubBranch(name, commit.sha, commit.url)
10 | }
--------------------------------------------------------------------------------
/platform-android/src/main/kotlin/com/multiplatform/model/api/entity/ApiCommit.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.api.entity
2 |
3 | data class ApiCommit(
4 | val sha: String,
5 | val url: String
6 | )
7 |
--------------------------------------------------------------------------------
/platform-android/src/main/kotlin/com/multiplatform/model/api/entity/ApiRepo.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.api.entity
2 |
3 | import com.multiplatform.model.entity.GithubRepo
4 |
5 | data class ApiRepo(
6 | val id: Long,
7 | val name: String
8 | ) {
9 | fun toGithubRepo() = GithubRepo(id, name)
10 | }
--------------------------------------------------------------------------------
/platform-android/src/main/kotlin/com/multiplatform/model/repository/ReposRepository.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.repository
2 |
3 | import com.jakewharton.retrofit2.adapter.kotlin.coroutines.experimental.CoroutineCallAdapterFactory
4 | import com.multiplatform.model.api.GithubApi
5 | import com.multiplatform.model.entity.GithubRepo
6 | import retrofit2.Retrofit
7 | import retrofit2.converter.gson.GsonConverterFactory
8 |
9 | actual class ReposRepository(
10 | private val baseUrl: String,
11 | private val userName: String
12 | ) {
13 | private val api: GithubApi by lazy {
14 | Retrofit.Builder()
15 | .addConverterFactory(GsonConverterFactory.create())
16 | .addCallAdapterFactory(CoroutineCallAdapterFactory())
17 | .baseUrl(baseUrl)
18 | .build()
19 | .create(GithubApi::class.java)
20 | }
21 |
22 | actual suspend fun getRepositories() =
23 | api.getRepositories(userName)
24 | .await()
25 | .map { apiRepo -> apiRepo.toGithubRepo() }
26 |
27 | actual suspend fun getBranches(repo: GithubRepo) =
28 | api.getBranches(userName, repo.name)
29 | .await()
30 | .map { apiBranch -> apiBranch.toGithubBranch() }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/platform-ios/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | maven { url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies" }
5 | }
6 |
7 | dependencies {
8 | classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$kotlin_native_version"
9 | }
10 | }
11 |
12 | apply plugin: 'konan'
13 |
14 | konanArtifacts {
15 |
16 | framework('KMulti', targets: ['iphone_sim']) {
17 |
18 | // Enable multiplatform support for this artifact.
19 | enableMultiplatform true
20 |
21 | // Enable compiler optimizations (true/false).
22 | enableOptimizations true
23 |
24 | // Enable debugging for binaries generated (true/false).
25 | enableDebug true
26 |
27 | // Print all parameters during the build.
28 | dumpParameters false
29 |
30 | // Print time of compilation phases (equivalent of the `--time` command line option).
31 | measureTime false
32 | }
33 |
34 | }
35 |
36 | dependencies {
37 | expectedBy project(':common')
38 | }
39 |
--------------------------------------------------------------------------------
/platform-ios/src/main/kotlin/com/multiplatform/coroutines/AsyncDispatcher.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.coroutines
2 |
3 | import kotlin.coroutines.experimental.*
4 | import kotlin.coroutines.experimental.intrinsics.*
5 |
6 | import konan.worker.*
7 |
8 | class DataObject(val value: T, val continuation: Continuation)
9 | class ErrorObject(val exception: Throwable, val continuation: Continuation)
10 |
11 | class AsyncDispatcher : ContinuationDispatcher() {
12 |
13 | val worker = startWorker()
14 |
15 | override fun dispatchResume(value: T, continuation: Continuation): Boolean {
16 | worker.schedule(TransferMode.UNCHECKED, {DataObject(value, continuation)}) {
17 | it.continuation.resume(it.value)
18 | }
19 | return true
20 | }
21 |
22 | override fun dispatchResumeWithException(exception: Throwable, continuation: Continuation<*>): Boolean {
23 | worker.schedule(TransferMode.UNCHECKED, {ErrorObject(exception, continuation)}) {
24 | it.continuation.resumeWithException(it.exception)
25 | }
26 | return false
27 | }
28 | }
--------------------------------------------------------------------------------
/platform-ios/src/main/kotlin/com/multiplatform/coroutines/ContinuationDispatcher.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.coroutines
2 |
3 | import kotlin.coroutines.experimental.*
4 | import kotlin.coroutines.experimental.intrinsics.*
5 |
6 | import platform.darwin.*
7 |
8 | abstract class ContinuationDispatcher :
9 | AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
10 |
11 | abstract fun dispatchResume(value: T, continuation: Continuation): Boolean
12 | abstract fun dispatchResumeWithException(exception: Throwable, continuation: Continuation<*>): Boolean
13 | override fun interceptContinuation(continuation: Continuation): Continuation {
14 | return DispatchedContinuation(this, continuation)
15 | }
16 | }
17 |
18 | internal class DispatchedContinuation(
19 | private val dispatcher: ContinuationDispatcher,
20 | private val continuation: Continuation
21 | ) : Continuation {
22 |
23 | override val context: CoroutineContext = continuation.context
24 |
25 | override fun resume(value: T) {
26 | if (dispatcher.dispatchResume(value, continuation).not()) {
27 | continuation.resume(value)
28 | }
29 | }
30 |
31 | override fun resumeWithException(exception: Throwable) {
32 | if (dispatcher.dispatchResumeWithException(exception, continuation).not()) {
33 | continuation.resumeWithException(exception)
34 | }
35 | }
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/platform-ios/src/main/kotlin/com/multiplatform/coroutines/Coroutines.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.coroutines
2 |
3 | import kotlin.coroutines.experimental.*
4 | import kotlin.coroutines.experimental.intrinsics.*
5 |
6 | typealias NativeDeferred = com.multiplatform.coroutines.Deferred
7 |
8 | actual fun async(context: CoroutineContext, block: suspend () -> T): NativeDeferred {
9 | return NativeDeferred(context, block)
10 | }
11 |
12 | actual fun launch(context: CoroutineContext, block: suspend () -> T) {
13 | block.startCoroutine(EmptyContinuation(context))
14 | }
15 |
16 | actual suspend fun withContext(context: CoroutineContext, block: suspend () -> T): T {
17 | return suspendCoroutineOrReturn { continuation ->
18 | block.startCoroutine(WrappedContinuation(context, continuation))
19 | COROUTINE_SUSPENDED
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/platform-ios/src/main/kotlin/com/multiplatform/coroutines/Deferred.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.coroutines
2 |
3 | import kotlin.coroutines.experimental.*
4 | import kotlin.coroutines.experimental.intrinsics.*
5 |
6 | actual class Deferred(
7 | private val context: CoroutineContext,
8 | private val block: suspend () -> T
9 | ) {
10 |
11 | actual suspend fun await(): T {
12 | return suspendCoroutineOrReturn { continuation ->
13 | block.startCoroutine(WrappedContinuation(context, continuation))
14 | COROUTINE_SUSPENDED
15 | }
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/platform-ios/src/main/kotlin/com/multiplatform/coroutines/MainQueueDispatcher.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.coroutines
2 |
3 | import kotlin.coroutines.experimental.*
4 | import kotlin.coroutines.experimental.intrinsics.*
5 |
6 | import platform.darwin.*
7 |
8 | class MainQueueDispatcher : ContinuationDispatcher() {
9 |
10 | override fun dispatchResume(value: T, continuation: Continuation): Boolean {
11 | dispatch_async(dispatch_get_main_queue()) {
12 | continuation.resume(value)
13 | }
14 | return true
15 | }
16 |
17 | override fun dispatchResumeWithException(exception: Throwable, continuation: Continuation<*>): Boolean {
18 | dispatch_async(dispatch_get_main_queue()) {
19 | continuation.resumeWithException(exception)
20 | }
21 | return true
22 | }
23 | }
--------------------------------------------------------------------------------
/platform-ios/src/main/kotlin/com/multiplatform/model/repository/ReposRepository.kt:
--------------------------------------------------------------------------------
1 | package com.multiplatform.model.repository
2 |
3 | import com.multiplatform.model.entity.GithubBranch
4 | import com.multiplatform.model.entity.GithubRepo
5 |
6 | import kotlin.coroutines.experimental.*
7 | import kotlin.coroutines.experimental.intrinsics.*
8 |
9 | actual open class ReposRepository {
10 |
11 | actual suspend fun getRepositories(): List {
12 | return suspendCoroutineOrReturn { continuation ->
13 | getRepositories(continuation)
14 | COROUTINE_SUSPENDED
15 | }
16 | }
17 |
18 | actual suspend fun getBranches(repo: GithubRepo): List {
19 | return suspendCoroutineOrReturn { continuation ->
20 | getBranches(repo, continuation)
21 | COROUTINE_SUSPENDED
22 | }
23 | }
24 |
25 | open fun getRepositories(callback: Continuation>) {
26 | throw NotImplementedError("iOS project should implement this")
27 | }
28 |
29 | open fun getBranches(repo: GithubRepo, callback: Continuation>) {
30 | throw NotImplementedError("iOS project should implement this")
31 | }
32 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'multiplatform'
2 | include 'common', 'platform-ios', 'platform-android', 'android'
3 |
4 |
--------------------------------------------------------------------------------