diff --git a/desktop/src-common/advent/iap.clj b/desktop/src-common/advent/iap.clj new file mode 100644 index 00000000..069d8fa6 --- /dev/null +++ b/desktop/src-common/advent/iap.clj @@ -0,0 +1,34 @@ +(ns advent.iap + (:import [com.badlogic.gdx Gdx Application]) + (:require [clojure.core.async :as a] + [advent.utils :as utils])) + +(def purchase-chan (a/chan 1)) +(def has-purchased? (atom false)) +(def can-purchase? (atom false)) + +(defn set-purchase-pref [val] + (println "setting preference purchased:" val) + (let [prefs (.getPreferences (Gdx/app) "purchases")] + (.putBoolean prefs "has-purchased?" val) + (.flush prefs)) + (reset! has-purchased? val) + (a/go (a/>! purchase-chan val))) + +(defn check-purchase-pref [] + (let [prefs (.getPreferences (Gdx/app) "purchases")] + (if (.contains prefs "has-purchased?") + (.getBoolean prefs "has-purchased?") + false))) + +(defn use-pref [] + (swap! has-purchased? #(or % (check-purchase-pref))) + (println "preferences purchased:" @has-purchased?)) + +(defn start-purchase [] + (utils/platformify + (do + (require '[advent.ios]) + (@(resolve 'advent.ios/start-purchase)) ) + (.triggerPurchase (Gdx/app)) + (set-purchase-pref true))) diff --git a/ios/resources/Icon-1024x1024.png b/ios/resources/Icon-1024x1024.png new file mode 100644 index 00000000..17bef1d0 Binary files /dev/null and b/ios/resources/Icon-1024x1024.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/1024x1024.png b/ios/resources/Images.xcassets/AppIcon.appiconset/1024x1024.png new file mode 100644 index 00000000..b3c98d29 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/1024x1024.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/29x29.png b/ios/resources/Images.xcassets/AppIcon.appiconset/29x29.png new file mode 100644 index 00000000..102ff73f Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/29x29.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/29x29@2x-1.png b/ios/resources/Images.xcassets/AppIcon.appiconset/29x29@2x-1.png new file mode 100644 index 00000000..8b7f1d9e Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/29x29@2x-1.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/29x29@2x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/29x29@2x.png new file mode 100644 index 00000000..8b7f1d9e Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/29x29@2x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/29x29@3x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/29x29@3x.png new file mode 100644 index 00000000..6b16cd76 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/29x29@3x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/Contents.json b/ios/resources/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..81b5d9d1 --- /dev/null +++ b/ios/resources/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "icon-large20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "icon-large20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-large40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-large40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "icon-large20x20.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "icon-large20x20@2x-1.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "29x29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "29x29@2x-1.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-large40x40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-large40x40@2x-1.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-large76x76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-large76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "1024x1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-1024x1024.png b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-1024x1024.png new file mode 100644 index 00000000..17bef1d0 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-1024x1024.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png new file mode 100644 index 00000000..e354b152 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png new file mode 100644 index 00000000..9755537c Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-76.png b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100644 index 00000000..1c10a3b0 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png new file mode 100644 index 00000000..c91a39b9 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png new file mode 100644 index 00000000..c973b9e2 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/Icon.png b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon.png new file mode 100644 index 00000000..83655ddc Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/Icon@2x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon@2x.png new file mode 100644 index 00000000..fc5c052f Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/Icon@2x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20.png new file mode 100644 index 00000000..9d0f808f Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20@2x-1.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20@2x-1.png new file mode 100644 index 00000000..1b6f2b28 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20@2x-1.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20@2x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20@2x.png new file mode 100644 index 00000000..1b6f2b28 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20@2x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20@3x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20@3x.png new file mode 100644 index 00000000..cbc5e6df Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large20x20@3x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40.png new file mode 100644 index 00000000..1b6f2b28 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40@2x-1.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40@2x-1.png new file mode 100644 index 00000000..8ff489f8 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40@2x-1.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40@2x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40@2x.png new file mode 100644 index 00000000..8ff489f8 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40@2x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40@3x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40@3x.png new file mode 100644 index 00000000..fe1bf564 Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large40x40@3x.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large76x76.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large76x76.png new file mode 100644 index 00000000..9316700e Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large76x76.png differ diff --git a/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large76x76@2x.png b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large76x76@2x.png new file mode 100644 index 00000000..e527fceb Binary files /dev/null and b/ios/resources/Images.xcassets/AppIcon.appiconset/icon-large76x76@2x.png differ diff --git a/ios/resources/Images.xcassets/Contents.json b/ios/resources/Images.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/ios/resources/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/src/clojure/advent/ios.clj b/ios/src/clojure/advent/ios.clj new file mode 100644 index 00000000..cee634e5 --- /dev/null +++ b/ios/src/clojure/advent/ios.clj @@ -0,0 +1,55 @@ +(ns advent.ios + (:require [advent.iap :as iap]) + (:import [org.robovm.apple.storekit SKProductsResponse SKProduct SKMutablePayment SKPaymentQueue SKPaymentTransactionState])) + +(def product (atom nil)) + +(defn products-did-receive-response [request ^SKProductsResponse response] + (reset! iap/can-purchase? true) + (reset! product (first (seq (.toArray (.getProducts response)))))) + +(defn products-did-fail [request error] + ) + +(defn products-did-finish [request] + ) + +(defn start-purchase [] + (try + (.addPayment (SKPaymentQueue/getDefaultQueue) + (doto (SKMutablePayment. @product) + (.setQuantity 1))) + (catch Exception e + (println e)))) + + + +(defn updated-transactions [queue, transactions] + + (let [purchased-states #{SKPaymentTransactionState/Purchased SKPaymentTransactionState/Restored} + finished-states #{SKPaymentTransactionState/Purchased SKPaymentTransactionState/Restored SKPaymentTransactionState/Failed SKPaymentTransactionState/Deferred} + is-finished (->> transactions + .toArray + seq + (every? #(finished-states (.getTransactionState %)))) + + has-purchased (->> transactions + .toArray + seq + (filter #(purchased-states (.getTransactionState %))) + (map #(-> % (.getPayment) (.getProductIdentifier))) + (filter #(= % "fullgame")) + seq)] + (when is-finished + (iap/set-purchase-pref (if has-purchased true false)) + (doseq [^SKPaymentTransaction trans (->> transactions .toArray seq)] + (.finishTransaction (SKPaymentQueue/getDefaultQueue) trans))))) + +(defn updated-downloads [queue, downloads] + (println "updated downloads" downloads)) +(defn restore-completed-transactions-finished [queue] + (println "transactions finished")) +(defn restore-completed-transactions-failed [queue, error] + (println "transactions failed")) +(defn removed-transactions [queue, transactions] + (println "transactions removed" transactions)) diff --git a/ios/src/java/advent/core/ProductDelegate.java b/ios/src/java/advent/core/ProductDelegate.java new file mode 100644 index 00000000..9f93c5bc --- /dev/null +++ b/ios/src/java/advent/core/ProductDelegate.java @@ -0,0 +1,33 @@ +package advent.core; + +import java.util.*; +import clojure.lang.RT; +import clojure.lang.Symbol; +import clojure.lang.IFn; + +import com.badlogic.gdx.*; +import com.badlogic.gdx.backends.iosrobovm.*; + +import org.robovm.apple.foundation.*; +import org.robovm.apple.uikit.UIApplication; +import org.robovm.apple.glkit.GLKViewDrawableColorFormat; +import org.robovm.apple.glkit.GLKViewDrawableDepthFormat; +import org.robovm.apple.storekit.*; + +public class ProductDelegate extends SKProductsRequestDelegateAdapter { + + @Override + public void didReceiveResponse(SKProductsRequest request, SKProductsResponse response) { + ((IFn) RT.var("advent.ios", "products-did-receive-response").deref()).invoke(request, response); + } + + @Override + public void didFail(SKRequest request, NSError error) { + ((IFn) RT.var("advent.ios", "products-did-fail").deref()).invoke(request, error); + } + + @Override + public void didFinish(SKRequest request) { + ((IFn) RT.var("advent.ios", "products-did-finish").deref()).invoke(request); + } +} diff --git a/ios/src/java/advent/core/TransactionObserver.java b/ios/src/java/advent/core/TransactionObserver.java new file mode 100644 index 00000000..549215c1 --- /dev/null +++ b/ios/src/java/advent/core/TransactionObserver.java @@ -0,0 +1,43 @@ +package advent.core; + +import java.util.*; +import clojure.lang.RT; +import clojure.lang.Symbol; +import clojure.lang.IFn; + +import com.badlogic.gdx.*; +import com.badlogic.gdx.backends.iosrobovm.*; + +import org.robovm.apple.foundation.*; +import org.robovm.apple.uikit.UIApplication; +import org.robovm.apple.glkit.GLKViewDrawableColorFormat; +import org.robovm.apple.glkit.GLKViewDrawableDepthFormat; +import org.robovm.apple.storekit.*; + +public class TransactionObserver extends SKPaymentTransactionObserverAdapter { + + @Override + public void updatedTransactions(SKPaymentQueue queue, NSArray transactions) { + ((IFn) RT.var("advent.ios", "updated-transactions").deref()).invoke(queue, transactions); + } + + @Override + public void updatedDownloads(SKPaymentQueue queue, NSArray downloads) { + ((IFn) RT.var("advent.ios", "updated-downloads").deref()).invoke(queue, downloads); + } + + @Override + public void restoreCompletedTransactionsFinished(SKPaymentQueue queue) { + ((IFn) RT.var("advent.ios", "restore-completed-transactions-finished").deref()).invoke(queue); + } + + @Override + public void restoreCompletedTransactionsFailed(SKPaymentQueue queue, NSError error) { + ((IFn) RT.var("advent.ios", "restore-completed-transactions-failed").deref()).invoke(queue, error); + } + + @Override + public void removedTransactions(SKPaymentQueue queue, NSArray transactions) { + ((IFn) RT.var("advent.ios", "removed-transactions").deref()).invoke(queue, transactions); + } +}