├── .gitignore ├── README.md ├── android ├── .classpath.example ├── .gitignore ├── .project ├── .settings │ ├── org.eclipse.jdt.apt.core.prefs │ └── org.eclipse.jdt.core.prefs ├── LICENSE ├── README.md ├── build.properties.example ├── build.xml ├── dist │ ├── se.hyperlab.mixpanel-android-0.1.zip │ ├── se.hyperlab.mixpanel-android-0.2.zip │ ├── se.hyperlab.mixpanel-android-0.3.zip │ ├── se.hyperlab.mixpanel-android-0.4.zip │ ├── se.hyperlab.mixpanel-android-0.5.zip │ ├── se.hyperlab.mixpanel-android-0.6.zip │ ├── se.hyperlab.mixpanel-android-0.7.zip │ ├── se.hyperlab.mixpanel-android-0.8.zip │ ├── se.hyperlab.mixpanel-android-0.9.zip │ └── timixpanel.jar ├── documentation │ └── index.md ├── example │ └── app.js ├── hooks │ ├── README │ ├── add.py │ ├── install.py │ ├── remove.py │ └── uninstall.py ├── lib │ └── mixpanel-android-4.4.1.jar ├── manifest ├── platform │ ├── README │ └── android │ │ └── res │ │ ├── anim │ │ ├── com_mixpanel_android_fade_in.xml │ │ ├── com_mixpanel_android_fade_out.xml │ │ └── com_mixpanel_android_slide_down.xml │ │ ├── drawable-hdpi-v4 │ │ ├── com_mixpanel_android_arrowleft.png │ │ ├── com_mixpanel_android_arrowleft_faded.png │ │ ├── com_mixpanel_android_arrowright.png │ │ ├── com_mixpanel_android_arrowright_faded.png │ │ ├── com_mixpanel_android_checkmark.png │ │ ├── com_mixpanel_android_logo.png │ │ ├── com_mixpanel_android_square_dropshadow.9.png │ │ └── com_mixpanel_android_square_nodropshadow.9.png │ │ ├── drawable-ldpi-v4 │ │ ├── com_mixpanel_android_arrowleft.png │ │ ├── com_mixpanel_android_arrowleft_faded.png │ │ ├── com_mixpanel_android_arrowright.png │ │ ├── com_mixpanel_android_arrowright_faded.png │ │ ├── com_mixpanel_android_checkmark.png │ │ └── com_mixpanel_android_logo.png │ │ ├── drawable-mdpi-v4 │ │ ├── com_mixpanel_android_arrowleft.png │ │ ├── com_mixpanel_android_arrowleft_faded.png │ │ ├── com_mixpanel_android_arrowright.png │ │ ├── com_mixpanel_android_arrowright_faded.png │ │ ├── com_mixpanel_android_checkmark.png │ │ ├── com_mixpanel_android_logo.png │ │ ├── com_mixpanel_android_square_dropshadow.9.png │ │ └── com_mixpanel_android_square_nodropshadow.9.png │ │ ├── drawable-nodpi-v4 │ │ ├── com_mixpanel_android_close.png │ │ ├── com_mixpanel_android_rounded_bottom.9.png │ │ ├── com_mixpanel_android_rounded_bottom_selected.9.png │ │ ├── com_mixpanel_android_rounded_top.9.png │ │ ├── com_mixpanel_android_rounded_top_selected.9.png │ │ ├── com_mixpanel_android_square.9.png │ │ └── com_mixpanel_android_square_selected.9.png │ │ ├── drawable-xhdpi-v4 │ │ ├── com_mixpanel_android_arrowleft.png │ │ ├── com_mixpanel_android_arrowleft_faded.png │ │ ├── com_mixpanel_android_arrowright.png │ │ ├── com_mixpanel_android_arrowright_faded.png │ │ ├── com_mixpanel_android_checkmark.png │ │ ├── com_mixpanel_android_logo.png │ │ ├── com_mixpanel_android_square_dropshadow.9.png │ │ └── com_mixpanel_android_square_nodropshadow.9.png │ │ ├── drawable-xxhdpi-v4 │ │ ├── com_mixpanel_android_arrowleft.png │ │ ├── com_mixpanel_android_arrowleft_faded.png │ │ ├── com_mixpanel_android_arrowright.png │ │ ├── com_mixpanel_android_arrowright_faded.png │ │ ├── com_mixpanel_android_checkmark.png │ │ ├── com_mixpanel_android_logo.png │ │ ├── com_mixpanel_android_square_dropshadow.9.png │ │ └── com_mixpanel_android_square_nodropshadow.9.png │ │ ├── drawable │ │ ├── com_mixpanel_android_arrowleft_insets.xml │ │ ├── com_mixpanel_android_arrowleft_states.xml │ │ ├── com_mixpanel_android_arrowright_insets.xml │ │ ├── com_mixpanel_android_arrowright_states.xml │ │ ├── com_mixpanel_android_checkmark_states.xml │ │ ├── com_mixpanel_android_choice_first_states.xml │ │ ├── com_mixpanel_android_choice_last_states.xml │ │ ├── com_mixpanel_android_choice_middle_states.xml │ │ ├── com_mixpanel_android_cta_button.xml │ │ ├── com_mixpanel_android_cta_button_highlight.xml │ │ ├── com_mixpanel_android_nocolor_list.xml │ │ └── com_mixpanel_android_text_answer_border.xml │ │ ├── layout-land │ │ └── com_mixpanel_android_activity_notification_full.xml │ │ ├── layout │ │ ├── com_mixpanel_android_activity_notification_full.xml │ │ ├── com_mixpanel_android_activity_notification_mini.xml │ │ ├── com_mixpanel_android_activity_survey.xml │ │ ├── com_mixpanel_android_first_choice_answer.xml │ │ ├── com_mixpanel_android_last_choice_answer.xml │ │ ├── com_mixpanel_android_middle_choice_answer.xml │ │ └── com_mixpanel_android_question_card.xml │ │ ├── values-v11 │ │ └── values.xml │ │ ├── values-v14 │ │ └── values.xml │ │ └── values │ │ └── values.xml ├── src │ └── se │ │ └── hyperlab │ │ └── mixpanel │ │ └── TimixpanelModule.java └── timodule.xml └── ios ├── .gitignore ├── Classes ├── .gitignore ├── SeHyperlabMixpanelModule.h ├── SeHyperlabMixpanelModule.m ├── SeHyperlabMixpanelModuleAssets.h └── SeHyperlabMixpanelModuleAssets.m ├── LICENSE ├── README.md ├── SeHyperlabMixpanel_Prefix.pch ├── TiMixpanel.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── Vendor ├── JRSwizzle │ ├── JRSwizzle.h │ └── JRSwizzle.m └── Mixpanel │ ├── MPABTestDesignerChangeRequestMessage.h │ ├── MPABTestDesignerChangeRequestMessage.m │ ├── MPABTestDesignerChangeResponseMessage.h │ ├── MPABTestDesignerChangeResponseMessage.m │ ├── MPABTestDesignerClearRequestMessage.h │ ├── MPABTestDesignerClearRequestMessage.m │ ├── MPABTestDesignerClearResponseMessage.h │ ├── MPABTestDesignerClearResponseMessage.m │ ├── MPABTestDesignerConnection.h │ ├── MPABTestDesignerConnection.m │ ├── MPABTestDesignerDeviceInfoRequestMessage.h │ ├── MPABTestDesignerDeviceInfoRequestMessage.m │ ├── MPABTestDesignerDeviceInfoResponseMessage.h │ ├── MPABTestDesignerDeviceInfoResponseMessage.m │ ├── MPABTestDesignerDisconnectMessage.h │ ├── MPABTestDesignerDisconnectMessage.m │ ├── MPABTestDesignerMessage.h │ ├── MPABTestDesignerSnapshotRequestMessage.h │ ├── MPABTestDesignerSnapshotRequestMessage.m │ ├── MPABTestDesignerSnapshotResponseMessage.h │ ├── MPABTestDesignerSnapshotResponseMessage.m │ ├── MPABTestDesignerTweakRequestMessage.h │ ├── MPABTestDesignerTweakRequestMessage.m │ ├── MPABTestDesignerTweakResponseMessage.h │ ├── MPABTestDesignerTweakResponseMessage.m │ ├── MPAbstractABTestDesignerMessage.h │ ├── MPAbstractABTestDesignerMessage.m │ ├── MPApplicationStateSerializer.h │ ├── MPApplicationStateSerializer.m │ ├── MPBOOLToNSNumberValueTransformer.m │ ├── MPCATransform3DToNSDictionaryValueTransformer.m │ ├── MPCGAffineTransformToNSDictionaryValueTransformer.m │ ├── MPCGColorRefToNSStringValueTransformer.m │ ├── MPCGPointToNSDictionaryValueTransformer.m │ ├── MPCGRectToNSDictionaryValueTransformer.m │ ├── MPCGSizeToNSDictionaryValueTransformer.m │ ├── MPCategoryHelpers.h │ ├── MPClassDescription.h │ ├── MPClassDescription.m │ ├── MPCloseBtn.png │ ├── MPCloseBtn@2x.png │ ├── MPDesignerEventBindingMessage.h │ ├── MPDesignerEventBindingRequestMesssage.m │ ├── MPDesignerEventBindingResponseMesssage.m │ ├── MPDesignerSessionCollection.h │ ├── MPDesignerTrackMessage.m │ ├── MPEnumDescription.h │ ├── MPEnumDescription.m │ ├── MPEventBinding.h │ ├── MPEventBinding.m │ ├── MPLogging.h │ ├── MPNSAttributedStringToNSDictionaryValueTransformer.m │ ├── MPNSNumberToCGFloatValueTransformer.m │ ├── MPNotification.h │ ├── MPNotification.m │ ├── MPNotification.storyboard │ ├── MPNotificationViewController.h │ ├── MPNotificationViewController.m │ ├── MPObjectIdentifierProvider.h │ ├── MPObjectIdentityProvider.h │ ├── MPObjectIdentityProvider.m │ ├── MPObjectSelector.h │ ├── MPObjectSelector.m │ ├── MPObjectSerializer.h │ ├── MPObjectSerializer.m │ ├── MPObjectSerializerConfig.h │ ├── MPObjectSerializerConfig.m │ ├── MPObjectSerializerContext.h │ ├── MPObjectSerializerContext.m │ ├── MPPassThroughValueTransformer.m │ ├── MPPropertyDescription.h │ ├── MPPropertyDescription.m │ ├── MPSequenceGenerator.h │ ├── MPSequenceGenerator.m │ ├── MPSurvey.h │ ├── MPSurvey.m │ ├── MPSurvey.storyboard │ ├── MPSurveyNavigationController.h │ ├── MPSurveyNavigationController.m │ ├── MPSurveyQuestion.h │ ├── MPSurveyQuestion.m │ ├── MPSurveyQuestionViewController.h │ ├── MPSurveyQuestionViewController.m │ ├── MPSwizzler.h │ ├── MPSwizzler.m │ ├── MPTweak.h │ ├── MPTweak.m │ ├── MPTweakInline.h │ ├── MPTweakInline.m │ ├── MPTweakInlineInternal.h │ ├── MPTweakStore.h │ ├── MPTweakStore.m │ ├── MPTypeDescription.h │ ├── MPTypeDescription.m │ ├── MPUIColorToNSStringValueTransformer.m │ ├── MPUIControlBinding.h │ ├── MPUIControlBinding.m │ ├── MPUIEdgeInsetsToNSDictionaryValueTransformer.m │ ├── MPUIFontToNSDictionaryValueTransformer.m │ ├── MPUIImageToNSDictionaryValueTransformer.m │ ├── MPUITableViewBinding.h │ ├── MPUITableViewBinding.m │ ├── MPValueTransformers.h │ ├── MPVariant.h │ ├── MPVariant.m │ ├── MPWebSocket.h │ ├── MPWebSocket.m │ ├── Media.xcassets │ ├── MPArrowLeft.imageset │ │ ├── Contents.json │ │ ├── MPArrowLeft.png │ │ └── MPArrowLeft@2x.png │ ├── MPArrowRight.imageset │ │ ├── Contents.json │ │ ├── MPArrowRight.png │ │ └── MPArrowRight@2x.png │ ├── MPCheckmark.imageset │ │ ├── Contents.json │ │ ├── MPCheckmark.png │ │ └── MPCheckmark@2x.png │ ├── MPCloseBtn.imageset │ │ ├── Contents.json │ │ ├── MPCloseBtn.png │ │ └── MPCloseBtn@2x.png │ ├── MPDismissKeyboard.imageset │ │ ├── Contents.json │ │ ├── MPDismissKeyboard.png │ │ └── MPDismissKeyboard@2x.png │ └── MPLogo.imageset │ │ ├── Contents.json │ │ ├── MPLogo.png │ │ └── MPLogo@2x.png │ ├── Mixpanel.h │ ├── Mixpanel.m │ ├── NSData+MPBase64.h │ ├── NSData+MPBase64.m │ ├── NSInvocation+MPHelpers.h │ ├── NSInvocation+MPHelpers.m │ ├── UIColor+MPColor.h │ ├── UIColor+MPColor.m │ ├── UIImage+MPAverageColor.h │ ├── UIImage+MPAverageColor.m │ ├── UIImage+MPImageEffects.h │ ├── UIImage+MPImageEffects.m │ ├── _MPTweakBindObserver.h │ ├── _MPTweakBindObserver.m │ ├── libMPCategoryHelpers.a │ ├── snapshot_config.json │ └── test_variant.json ├── assets └── README ├── build.py ├── compile-storyboards.sh ├── dist ├── se.hyperlab.mixpanel-iphone-0.1.zip ├── se.hyperlab.mixpanel-iphone-0.2.zip ├── se.hyperlab.mixpanel-iphone-0.3.zip ├── se.hyperlab.mixpanel-iphone-0.4.zip ├── se.hyperlab.mixpanel-iphone-0.5.zip ├── se.hyperlab.mixpanel-iphone-0.6.zip ├── se.hyperlab.mixpanel-iphone-0.7.zip └── se.hyperlab.mixpanel-iphone-0.8.zip ├── documentation └── index.md ├── example └── app.js ├── hooks ├── README ├── add.py ├── install.py ├── remove.py └── uninstall.py ├── manifest ├── module.xcconfig ├── platform ├── README └── iphone │ ├── MPArrowLeft.png │ ├── MPArrowLeft@2x.png │ ├── MPArrowRight.png │ ├── MPArrowRight@2x.png │ ├── MPCheckmark.png │ ├── MPCheckmark@2x.png │ ├── MPCloseBtn.png │ ├── MPCloseBtn@2x.png │ ├── MPDismissKeyboard.png │ ├── MPDismissKeyboard@2x.png │ ├── MPLogo.png │ ├── MPLogo@2x.png │ ├── MPNotification.storyboard │ └── MPSurvey.storyboard ├── timodule.xml └── titanium.xcconfig /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xcuserdata/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mixpanel Module for Titanium Mobile 2 | 3 | See the respective platform directory for more info. 4 | -------------------------------------------------------------------------------- /android/.classpath.example: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | libs 3 | bin 4 | build 5 | .apt_generated 6 | .classpath 7 | build.properties -------------------------------------------------------------------------------- /android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | TiMixpanel 4 | 5 | 6 | 7 | 8 | 9 | com.appcelerator.titanium.core.builder 10 | 11 | 12 | 13 | 14 | com.aptana.ide.core.unifiedBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | 25 | org.eclipse.jdt.core.javanature 26 | com.appcelerator.titanium.mobile.module.nature 27 | com.aptana.projects.webnature 28 | 29 | 30 | -------------------------------------------------------------------------------- /android/.settings/org.eclipse.jdt.apt.core.prefs: -------------------------------------------------------------------------------- 1 | #Thu Sep 02 15:18:34 CDT 2010 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.apt.aptEnabled=true 4 | org.eclipse.jdt.apt.genSrcDir=.apt_generated 5 | org.eclipse.jdt.apt.reconcileEnabled=true 6 | 7 | org.eclipse.jdt.apt.processorOptions/kroll.jsonFile=TiMixpanel.json 8 | -------------------------------------------------------------------------------- /android/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.5 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.processAnnotations=enabled 12 | org.eclipse.jdt.core.compiler.source=1.5 13 | -------------------------------------------------------------------------------- /android/LICENSE: -------------------------------------------------------------------------------- 1 | TODO: place your license here and we'll include it in the module distribution 2 | -------------------------------------------------------------------------------- /android/build.properties.example: -------------------------------------------------------------------------------- 1 | home=/Users/name 2 | android.sdk=${home}/Code/Android 3 | android.ndk=${android.sdk}/AndroidNDK 4 | titanium.sdk=${home}/Library/Application\ Support/Titanium/ 5 | titanium.os=osx 6 | titanium.version=3.5.1.GA 7 | 8 | titanium.platform=${titanium.sdk}/mobilesdk/${titanium.os}/${titanium.version}/android 9 | android.platform=${android.sdk}/platforms/android-10 10 | google.apis=${android.sdk}/add-ons/addon_google_apis_google_inc_10 11 | -------------------------------------------------------------------------------- /android/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ant build script for Titanium Android module TiMixpanel 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/dist/se.hyperlab.mixpanel-android-0.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/se.hyperlab.mixpanel-android-0.1.zip -------------------------------------------------------------------------------- /android/dist/se.hyperlab.mixpanel-android-0.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/se.hyperlab.mixpanel-android-0.2.zip -------------------------------------------------------------------------------- /android/dist/se.hyperlab.mixpanel-android-0.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/se.hyperlab.mixpanel-android-0.3.zip -------------------------------------------------------------------------------- /android/dist/se.hyperlab.mixpanel-android-0.4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/se.hyperlab.mixpanel-android-0.4.zip -------------------------------------------------------------------------------- /android/dist/se.hyperlab.mixpanel-android-0.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/se.hyperlab.mixpanel-android-0.5.zip -------------------------------------------------------------------------------- /android/dist/se.hyperlab.mixpanel-android-0.6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/se.hyperlab.mixpanel-android-0.6.zip -------------------------------------------------------------------------------- /android/dist/se.hyperlab.mixpanel-android-0.7.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/se.hyperlab.mixpanel-android-0.7.zip -------------------------------------------------------------------------------- /android/dist/se.hyperlab.mixpanel-android-0.8.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/se.hyperlab.mixpanel-android-0.8.zip -------------------------------------------------------------------------------- /android/dist/se.hyperlab.mixpanel-android-0.9.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/se.hyperlab.mixpanel-android-0.9.zip -------------------------------------------------------------------------------- /android/dist/timixpanel.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/dist/timixpanel.jar -------------------------------------------------------------------------------- /android/documentation/index.md: -------------------------------------------------------------------------------- 1 | # TiMixpanel Module 2 | 3 | ## Description 4 | 5 | TODO: Enter your module description here 6 | 7 | ## Accessing the TiMixpanel Module 8 | 9 | To access this module from JavaScript, you would do the following: 10 | 11 | var TiMixpanel = require("se.hyperlab.mixpanel"); 12 | 13 | The TiMixpanel variable is a reference to the Module object. 14 | 15 | ## Reference 16 | 17 | TODO: If your module has an API, you should document 18 | the reference here. 19 | 20 | ### ___PROJECTNAMEASIDENTIFIER__.function 21 | 22 | TODO: This is an example of a module function. 23 | 24 | ### ___PROJECTNAMEASIDENTIFIER__.property 25 | 26 | TODO: This is an example of a module property. 27 | 28 | ## Usage 29 | 30 | TODO: Enter your usage example here 31 | 32 | ## Author 33 | 34 | TODO: Enter your author name, email and other contact 35 | details you want to share here. 36 | 37 | ## License 38 | 39 | TODO: Enter your license/legal information here. 40 | -------------------------------------------------------------------------------- /android/example/app.js: -------------------------------------------------------------------------------- 1 | // Simple test UI 2 | var win = Ti.UI.createWindow({ 3 | backgroundColor:'white' 4 | }); 5 | var button = Ti.UI.createButton({ 6 | title: 'Track event' 7 | }); 8 | win.add(button); 9 | win.open(); 10 | 11 | 12 | // Mixpanel test/demo code, mirrors the iOS API fairly well 13 | // See: https://mixpanel.com/help/reference/ios 14 | 15 | var mixpanel = require('se.hyperlab.mixpanel'); 16 | mixpanel.initWithToken('YOUR-TOKEN-GOES-HERE'); 17 | 18 | // Enable GCM 19 | mixpanel.initPushHandling('YOUR-SENDER-ID-GOES-HERE'); 20 | 21 | // Flush queued data every 45 seconds (Instead of the default of 60 seconds) 22 | // mixpanel.flushInterval = 45; 23 | 24 | Ti.API.log('Mixpanel distinctId: ' + mixpanel.distinctId); 25 | 26 | // The same as: 27 | // mixpanel.createAliasForId('NEW-TEST-ID', mixpanel.distinctId); 28 | mixpanel.createAlias('NEW-TEST-ID'); 29 | 30 | mixpanel.identify('NEW-TEST-ID'); 31 | Ti.API.log('Mixpanel distinctId: ' + mixpanel.distinctId); 32 | 33 | mixpanel.registerSuperProperties({ 34 | 'Device Model': Ti.Platform.model, 35 | 'Application ID': Ti.App.id 36 | }); 37 | 38 | mixpanel.registerSuperPropertiesOnce({ 39 | 'Affiliate ID': '123abc' 40 | }); 41 | 42 | mixpanel.track('App Opened'); 43 | 44 | // Manually flush data to MixPanel 45 | mixpanel.flush(); 46 | 47 | button.addEventListener('click', function () { 48 | mixpanel.track('Custom Event', { 49 | 'Custom Prop': 'value' 50 | }); 51 | }); 52 | 53 | 54 | // User Profiles 55 | mixpanel.profileSet({ 56 | '$name': 'Full Name', 57 | '$email': 'test@example.com', 58 | 59 | key: 'value', 60 | special: 'once', 61 | num: 2, 62 | list: ['a'] 63 | }); 64 | mixpanel.profileSetOnce({ 65 | special: 'twice', // Wont update key 66 | }); 67 | 68 | 69 | mixpanel.profileIncrement({ 70 | num: 1 // To a total of 3 71 | }); 72 | mixpanel.profileAppend({ 73 | list: ['b', 'c'] 74 | }); 75 | 76 | mixpanel.profileTrackCharge(150); 77 | mixpanel.profileTrackCharge(100, { 78 | campaign: '123abc' 79 | }); 80 | -------------------------------------------------------------------------------- /android/hooks/README: -------------------------------------------------------------------------------- 1 | These files are not yet supported as of 1.4.0 but will be in a near future release. 2 | -------------------------------------------------------------------------------- /android/hooks/add.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module project add hook that will be 4 | # called when your module is added to a project 5 | # 6 | import os, sys 7 | 8 | def dequote(s): 9 | if s[0:1] == '"': 10 | return s[1:-1] 11 | return s 12 | 13 | def main(args,argc): 14 | # You will get the following command line arguments 15 | # in the following order: 16 | # 17 | # project_dir = the full path to the project root directory 18 | # project_type = the type of project (desktop, mobile, ipad) 19 | # project_name = the name of the project 20 | # 21 | project_dir = dequote(os.path.expanduser(args[1])) 22 | project_type = dequote(args[2]) 23 | project_name = dequote(args[3]) 24 | 25 | # TODO: write your add hook here (optional) 26 | 27 | 28 | # exit 29 | sys.exit(0) 30 | 31 | 32 | 33 | if __name__ == '__main__': 34 | main(sys.argv,len(sys.argv)) 35 | 36 | -------------------------------------------------------------------------------- /android/hooks/install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module install hook that will be 4 | # called when your module is first installed 5 | # 6 | import os, sys 7 | 8 | def main(args,argc): 9 | 10 | # TODO: write your install hook here (optional) 11 | 12 | # exit 13 | sys.exit(0) 14 | 15 | 16 | 17 | if __name__ == '__main__': 18 | main(sys.argv,len(sys.argv)) 19 | 20 | -------------------------------------------------------------------------------- /android/hooks/remove.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module project remove hook that will be 4 | # called when your module is remove from a project 5 | # 6 | import os, sys 7 | 8 | def dequote(s): 9 | if s[0:1] == '"': 10 | return s[1:-1] 11 | return s 12 | 13 | def main(args,argc): 14 | # You will get the following command line arguments 15 | # in the following order: 16 | # 17 | # project_dir = the full path to the project root directory 18 | # project_type = the type of project (desktop, mobile, ipad) 19 | # project_name = the name of the project 20 | # 21 | project_dir = dequote(os.path.expanduser(args[1])) 22 | project_type = dequote(args[2]) 23 | project_name = dequote(args[3]) 24 | 25 | # TODO: write your remove hook here (optional) 26 | 27 | # exit 28 | sys.exit(0) 29 | 30 | 31 | 32 | if __name__ == '__main__': 33 | main(sys.argv,len(sys.argv)) 34 | 35 | -------------------------------------------------------------------------------- /android/hooks/uninstall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module uninstall hook that will be 4 | # called when your module is uninstalled 5 | # 6 | import os, sys 7 | 8 | def main(args,argc): 9 | 10 | # TODO: write your uninstall hook here (optional) 11 | 12 | # exit 13 | sys.exit(0) 14 | 15 | 16 | if __name__ == '__main__': 17 | main(sys.argv,len(sys.argv)) 18 | 19 | -------------------------------------------------------------------------------- /android/lib/mixpanel-android-4.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/lib/mixpanel-android-4.4.1.jar -------------------------------------------------------------------------------- /android/manifest: -------------------------------------------------------------------------------- 1 | # 2 | # this is your module manifest and used by Titanium 3 | # during compilation, packaging, distribution, etc. 4 | # 5 | version: 0.9 6 | apiversion: 2 7 | description: Mixpanel integration for Titanium Mobile 8 | author: Jonatan Lundin 9 | license: MIT 10 | copyright: Copyright (C) 2014-2015 Hyperlab AB 11 | architectures: armeabi;armeabi-v7a;x86 12 | 13 | # these should not be edited 14 | name: TiMixpanel 15 | moduleid: se.hyperlab.mixpanel 16 | guid: 7031f78e-4cf3-4b12-98f0-99325bd1987e 17 | platform: android 18 | minsdk: 3.2.2.GA 19 | 20 | # Build Mixpanel SDK, to not conflict with Titanium's R.java 21 | respackage: com.mixpanel.android 22 | -------------------------------------------------------------------------------- /android/platform/README: -------------------------------------------------------------------------------- 1 | You can place platform-specific files here in sub-folders named "android" and/or "iphone", just as you can with normal Titanium Mobile SDK projects. Any folders and files you place here will be merged with the platform-specific files in a Titanium Mobile project that uses this module. 2 | 3 | When a Titanium Mobile project that uses this module is built, the files from this platform/ folder will be treated the same as files (if any) from the Titanium Mobile project's platform/ folder. 4 | -------------------------------------------------------------------------------- /android/platform/android/res/anim/com_mixpanel_android_fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/platform/android/res/anim/com_mixpanel_android_fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/platform/android/res/anim/com_mixpanel_android_slide_down.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_arrowleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_arrowleft.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_arrowleft_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_arrowleft_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_arrowright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_arrowright.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_arrowright_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_arrowright_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_checkmark.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_logo.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_square_dropshadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_square_dropshadow.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_square_nodropshadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-hdpi-v4/com_mixpanel_android_square_nodropshadow.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_arrowleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_arrowleft.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_arrowleft_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_arrowleft_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_arrowright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_arrowright.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_arrowright_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_arrowright_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_checkmark.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-ldpi-v4/com_mixpanel_android_logo.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_arrowleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_arrowleft.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_arrowleft_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_arrowleft_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_arrowright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_arrowright.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_arrowright_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_arrowright_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_checkmark.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_logo.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_square_dropshadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_square_dropshadow.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_square_nodropshadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-mdpi-v4/com_mixpanel_android_square_nodropshadow.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_close.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_rounded_bottom.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_rounded_bottom.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_rounded_bottom_selected.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_rounded_bottom_selected.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_rounded_top.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_rounded_top.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_rounded_top_selected.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_rounded_top_selected.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_square.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_square.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_square_selected.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-nodpi-v4/com_mixpanel_android_square_selected.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_arrowleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_arrowleft.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_arrowleft_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_arrowleft_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_arrowright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_arrowright.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_arrowright_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_arrowright_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_checkmark.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_logo.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_square_dropshadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_square_dropshadow.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_square_nodropshadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xhdpi-v4/com_mixpanel_android_square_nodropshadow.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_arrowleft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_arrowleft.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_arrowleft_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_arrowleft_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_arrowright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_arrowright.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_arrowright_faded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_arrowright_faded.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_checkmark.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_logo.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_square_dropshadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_square_dropshadow.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_square_nodropshadow.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/android/platform/android/res/drawable-xxhdpi-v4/com_mixpanel_android_square_nodropshadow.9.png -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_arrowleft_insets.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_arrowleft_states.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_arrowright_insets.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_arrowright_states.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_checkmark_states.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_choice_first_states.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_choice_last_states.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_choice_middle_states.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_cta_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_cta_button_highlight.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_nocolor_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/platform/android/res/drawable/com_mixpanel_android_text_answer_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /android/platform/android/res/layout/com_mixpanel_android_activity_notification_mini.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /android/platform/android/res/layout/com_mixpanel_android_activity_survey.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 17 | 18 | 27 | 28 | 36 | 37 | 46 | 47 | 48 | 54 | 55 | 59 | 60 | 69 | 70 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /android/platform/android/res/layout/com_mixpanel_android_first_choice_answer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /android/platform/android/res/layout/com_mixpanel_android_last_choice_answer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /android/platform/android/res/layout/com_mixpanel_android_middle_choice_answer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /android/platform/android/res/layout/com_mixpanel_android_question_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 16 | 17 | 28 | 29 | 43 | 44 | 45 | 56 | 57 | -------------------------------------------------------------------------------- /android/platform/android/res/values-v11/values.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /android/platform/android/res/values-v14/values.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /android/platform/android/res/values/values.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | #66ffffff 8 | 9 | Close 10 | Done 11 | Exit 12 | By Mixpanel 13 | Next question 14 | Image not displayed 15 | Previous question 16 | 17 | 18 | 19 | 23 | 24 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /android/timodule.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | bin 3 | build 4 | /*.zip 5 | .project 6 | .settings 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.xcuserstate 21 | *.storyboardc 22 | -------------------------------------------------------------------------------- /ios/Classes/.gitignore: -------------------------------------------------------------------------------- 1 | SeHyperlabMixpanel.h 2 | SeHyperlabMixpanel.m 3 | -------------------------------------------------------------------------------- /ios/Classes/SeHyperlabMixpanelModule.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2014 Hyperlab AB 3 | * 4 | * Appcelerator Titanium is Copyright (c) 2009-2010 by Appcelerator, Inc. 5 | * and licensed under the Apache Public License (version 2) 6 | */ 7 | #import "TiModule.h" 8 | 9 | @interface SeHyperlabMixpanelModule : TiModule 10 | { 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ios/Classes/SeHyperlabMixpanelModuleAssets.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a generated file. Do not edit or your changes will be lost 3 | */ 4 | 5 | @interface SeHyperlabMixpanelModuleAssets : NSObject 6 | { 7 | } 8 | - (NSData*) moduleAsset; 9 | - (NSData*) resolveModuleAsset:(NSString*)path; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /ios/Classes/SeHyperlabMixpanelModuleAssets.m: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a generated file. Do not edit or your changes will be lost 3 | */ 4 | #import "SeHyperlabMixpanelModuleAssets.h" 5 | 6 | extern NSData* filterDataInRange(NSData* thedata, NSRange range); 7 | 8 | @implementation SeHyperlabMixpanelModuleAssets 9 | 10 | - (NSData*) moduleAsset 11 | { 12 | //##TI_AUTOGEN_BEGIN asset 13 | //Compiler generates code for asset here 14 | return nil; // DEFAULT BEHAVIOR 15 | //##TI_AUTOGEN_END asset 16 | } 17 | 18 | - (NSData*) resolveModuleAsset:(NSString*)path 19 | { 20 | //##TI_AUTOGEN_BEGIN resolve_asset 21 | //Compiler generates code for asset resolution here 22 | return nil; // DEFAULT BEHAVIOR 23 | //##TI_AUTOGEN_END resolve_asset 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ios/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /ios/README.md: -------------------------------------------------------------------------------- 1 | # Mixpanel iOS Module 2 | 3 | ## Description 4 | 5 | Mixpanel module for Titanium Mobile. This module currently only exposes a subset of the full Mixpanel API. 6 | 7 | ## Usage 8 | 9 | Add the module to you project, the latest version of the module can be found inside the dist folder. See example/app.js for usage example. 10 | 11 | ## Known Issues 12 | 13 | * Not all the API is exposed at the moment 14 | 15 | ## Changes 16 | 17 | **0.8** 18 | - Surverys and In-App Notifications are back! 19 | 20 | **0.7** 21 | - Upgraded to Mixpanel SDK 2.6.0 22 | - Allow Mixpanel customers to define new elements to be tracked in their app dynamically without having to re-release to the app store. 23 | - You can track the time it took for an action to occur, such as an image upload or a comment post, using `timeEvent(String name)`. This will mark the "start" of your action, which you can then finish with a track call. The time duration is then recorded in the "Duration" property. 24 | 25 | **0.6** 26 | - Added support for 64-bit 27 | 28 | **0.5** 29 | - Device tokens were not correctly send to Mixpanel, breaking Push Notification support 30 | - Updated to latest version of Mixpanel iOS SDK, to support A/B tests 31 | 32 | **0.4** 33 | - Disabled Surveys and In-App Notifications, because they currently crash the app. (It is unfortunately not possible to include Storyboards in native modules) 34 | 35 | **0.3** 36 | - Added support for the following functions: 37 | - `flush`: Uploads queued data to the Mixpanel server manually. 38 | - `setFlushInterval`: function to set the flush interval in seconds. (By default, queued data is flushed to the Mixpanel servers every minute). 39 | - `addPushDeviceToken`: Register the given device to receive push notifications. Make sure to call `identify` first! 40 | - `reset`: Clears all stored properties and distinct IDs. Useful if your app's user logs out. 41 | - Upgraded MixPanel iOS SDK to version 2.3.6. 42 | 43 | **0.2** 44 | - Methods for managing user identity 45 | - People/profile tracking 46 | - Code cleanup 47 | 48 | **0.1** 49 | - Initial release 50 | 51 | ## Contributors 52 | 53 | **Jonatan Lundin** 54 | Web: http://hyperlab.se 55 | Twitter: @mr_lundis 56 | 57 | **Timan Rebel** 58 | Web: http://timanrebel.nl 59 | Twitter: @timanrebel 60 | 61 | **Iñaki Abete** 62 | Web: http://github.com/inakiabt 63 | Twitter: @inakiabt 64 | 65 | Initial code based on the [Titanium-Mixpanel-Module](https://github.com/meeech/Titanium-Mixpanel-Module) by @meeech. 66 | 67 | ## License 68 | 69 | The MIT License (MIT) 70 | 71 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 72 | 73 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 74 | 75 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 76 | -------------------------------------------------------------------------------- /ios/SeHyperlabMixpanel_Prefix.pch: -------------------------------------------------------------------------------- 1 | 2 | #ifdef __OBJC__ 3 | #import 4 | #import 5 | #endif 6 | -------------------------------------------------------------------------------- /ios/TiMixpanel.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Vendor/JRSwizzle/JRSwizzle.h: -------------------------------------------------------------------------------- 1 | // JRSwizzle.h semver:1.0 2 | // Copyright (c) 2007-2011 Jonathan 'Wolf' Rentzsch: http://rentzsch.com 3 | // Some rights reserved: http://opensource.org/licenses/MIT 4 | // https://github.com/rentzsch/jrswizzle 5 | 6 | #import 7 | 8 | @interface NSObject (JRSwizzle) 9 | 10 | + (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_; 11 | + (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerChangeRequestMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPAbstractABTestDesignerMessage.h" 6 | 7 | extern NSString *const MPABTestDesignerChangeRequestMessageType; 8 | 9 | @interface MPABTestDesignerChangeRequestMessage : MPAbstractABTestDesignerMessage 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerChangeRequestMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPABTestDesignerChangeRequestMessage.h" 5 | #import "MPABTestDesignerChangeResponseMessage.h" 6 | #import "MPABTestDesignerConnection.h" 7 | #import "MPABTestDesignerSnapshotResponseMessage.h" 8 | #import "MPVariant.h" 9 | 10 | NSString *const MPABTestDesignerChangeRequestMessageType = @"change_request"; 11 | 12 | @implementation MPABTestDesignerChangeRequestMessage 13 | 14 | + (instancetype)message 15 | { 16 | return [[self alloc] initWithType:MPABTestDesignerChangeRequestMessageType]; 17 | } 18 | 19 | - (NSOperation *)responseCommandWithConnection:(MPABTestDesignerConnection *)connection 20 | { 21 | __weak MPABTestDesignerConnection *weak_connection = connection; 22 | NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 23 | MPABTestDesignerConnection *conn = weak_connection; 24 | 25 | MPVariant *variant = [connection sessionObjectForKey:kSessionVariantKey]; 26 | if (!variant) { 27 | variant = [[MPVariant alloc] init]; 28 | [connection setSessionObject:variant forKey:kSessionVariantKey]; 29 | } 30 | 31 | if ([[[self payload] objectForKey:@"actions"] isKindOfClass:[NSArray class]]) { 32 | dispatch_sync(dispatch_get_main_queue(), ^{ 33 | [variant addActionsFromJSONObject:[[self payload] objectForKey:@"actions"] andExecute:YES]; 34 | }); 35 | } 36 | 37 | MPABTestDesignerChangeResponseMessage *changeResponseMessage = [MPABTestDesignerChangeResponseMessage message]; 38 | changeResponseMessage.status = @"OK"; 39 | [conn sendMessage:changeResponseMessage]; 40 | }]; 41 | 42 | return operation; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerChangeResponseMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPAbstractABTestDesignerMessage.h" 6 | 7 | @interface MPABTestDesignerChangeResponseMessage : MPAbstractABTestDesignerMessage 8 | 9 | + (instancetype)message; 10 | 11 | @property (nonatomic, copy) NSString *status; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerChangeResponseMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPABTestDesignerChangeResponseMessage.h" 5 | 6 | @implementation MPABTestDesignerChangeResponseMessage 7 | 8 | + (instancetype)message 9 | { 10 | return [[self alloc] initWithType:@"change_response"]; 11 | } 12 | 13 | - (void)setStatus:(NSString *)status 14 | { 15 | [self setPayloadObject:status forKey:@"status"]; 16 | } 17 | 18 | - (NSString *)status 19 | { 20 | return [self payloadObjectForKey:@"status"]; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerClearRequestMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPAbstractABTestDesignerMessage.h" 5 | 6 | extern NSString *const MPABTestDesignerClearRequestMessageType; 7 | 8 | @interface MPABTestDesignerClearRequestMessage : MPAbstractABTestDesignerMessage 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerClearRequestMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPABTestDesignerClearRequestMessage.m 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 3/7/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPABTestDesignerClearRequestMessage.h" 10 | #import "MPABTestDesignerClearResponseMessage.h" 11 | #import "MPABTestDesignerConnection.h" 12 | #import "MPVariant.h" 13 | 14 | NSString *const MPABTestDesignerClearRequestMessageType = @"clear_request"; 15 | 16 | @implementation MPABTestDesignerClearRequestMessage 17 | 18 | + (instancetype)message 19 | { 20 | return [[self alloc] initWithType:MPABTestDesignerClearRequestMessageType]; 21 | } 22 | 23 | - (NSOperation *)responseCommandWithConnection:(MPABTestDesignerConnection *)connection 24 | { 25 | __weak MPABTestDesignerConnection *weak_connection = connection; 26 | NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 27 | MPABTestDesignerConnection *conn = weak_connection; 28 | 29 | MPVariant *variant = [conn sessionObjectForKey:kSessionVariantKey]; 30 | if (variant) { 31 | NSArray *actions = [self.payload objectForKey:@"actions"]; 32 | dispatch_sync(dispatch_get_main_queue(), ^{ 33 | for (NSString *name in actions) { 34 | [variant removeActionWithName:name]; 35 | } 36 | }); 37 | } 38 | 39 | MPABTestDesignerClearResponseMessage *clearResponseMessage = [MPABTestDesignerClearResponseMessage message]; 40 | clearResponseMessage.status = @"OK"; 41 | [conn sendMessage:clearResponseMessage]; 42 | }]; 43 | return operation; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerClearResponseMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPABTestDesignerClearResponseMessage.h 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 3/7/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPAbstractABTestDesignerMessage.h" 10 | 11 | @interface MPABTestDesignerClearResponseMessage : MPAbstractABTestDesignerMessage 12 | 13 | + (instancetype)message; 14 | 15 | @property (nonatomic, copy) NSString *status; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerClearResponseMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPABTestDesignerClearResponseMessage.m 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 3/7/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPABTestDesignerClearResponseMessage.h" 10 | 11 | @implementation MPABTestDesignerClearResponseMessage 12 | 13 | + (instancetype)message 14 | { 15 | return [[self alloc] initWithType:@"clear_response"]; 16 | } 17 | 18 | - (void)setStatus:(NSString *)status 19 | { 20 | [self setPayloadObject:status forKey:@"status"]; 21 | } 22 | 23 | - (NSString *)status 24 | { 25 | return [self payloadObjectForKey:@"status"]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPWebSocket.h" 6 | 7 | @protocol MPABTestDesignerMessage; 8 | 9 | extern NSString *const kSessionVariantKey; 10 | 11 | @interface MPABTestDesignerConnection : NSObject 12 | 13 | @property (nonatomic, readonly) BOOL connected; 14 | @property (nonatomic, assign) BOOL sessionEnded; 15 | 16 | - (id)initWithURL:(NSURL *)url; 17 | - (id)initWithURL:(NSURL *)url connectCallback:(void (^)())connectCallback disconnectCallback:(void (^)())disconnectCallback; 18 | 19 | - (void)setSessionObject:(id)object forKey:(NSString *)key; 20 | - (id)sessionObjectForKey:(NSString *)key; 21 | - (void)sendMessage:(id)message; 22 | - (void)close; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerDeviceInfoRequestMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPAbstractABTestDesignerMessage.h" 6 | 7 | extern NSString *const MPABTestDesignerDeviceInfoRequestMessageType; 8 | 9 | @interface MPABTestDesignerDeviceInfoRequestMessage : MPAbstractABTestDesignerMessage 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerDeviceInfoResponseMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPAbstractABTestDesignerMessage.h" 6 | 7 | @interface MPABTestDesignerDeviceInfoResponseMessage : MPAbstractABTestDesignerMessage 8 | 9 | + (instancetype)message; 10 | 11 | @property (nonatomic, copy) NSString *systemName; 12 | @property (nonatomic, copy) NSString *systemVersion; 13 | @property (nonatomic, copy) NSString *appVersion; 14 | @property (nonatomic, copy) NSString *appRelease; 15 | @property (nonatomic, copy) NSString *deviceName; 16 | @property (nonatomic, copy) NSString *deviceModel; 17 | @property (nonatomic, copy) NSString *libVersion; 18 | @property (nonatomic, copy) NSArray *availableFontFamilies; 19 | @property (nonatomic, copy) NSString *mainBundleIdentifier; 20 | @property (nonatomic, copy) NSArray *tweaks; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerDeviceInfoResponseMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPABTestDesignerDeviceInfoResponseMessage.h" 5 | 6 | @implementation MPABTestDesignerDeviceInfoResponseMessage 7 | 8 | + (instancetype)message 9 | { 10 | // TODO: provide a payload 11 | return [[self alloc] initWithType:@"device_info_response"]; 12 | } 13 | 14 | - (NSString *)systemName 15 | { 16 | return [self payloadObjectForKey:@"system_name"]; 17 | } 18 | 19 | - (void)setSystemName:(NSString *)systemName 20 | { 21 | [self setPayloadObject:systemName forKey:@"system_name"]; 22 | } 23 | 24 | - (NSString *)systemVersion 25 | { 26 | return [self payloadObjectForKey:@"system_version"]; 27 | } 28 | 29 | - (void)setSystemVersion:(NSString *)systemVersion 30 | { 31 | [self setPayloadObject:systemVersion forKey:@"system_version"]; 32 | } 33 | 34 | - (NSString *)appVersion 35 | { 36 | return [self payloadObjectForKey:@"app_version"]; 37 | } 38 | 39 | - (void)setAppVersion:(NSString *)appVersion 40 | { 41 | [self setPayloadObject:appVersion forKey:@"app_version"]; 42 | } 43 | 44 | - (NSString *)appRelease 45 | { 46 | return [self payloadObjectForKey:@"app_release"]; 47 | } 48 | 49 | - (void)setAppRelease:(NSString *)appRelease 50 | { 51 | [self setPayloadObject:appRelease forKey:@"app_release"]; 52 | } 53 | 54 | - (NSString *)deviceName 55 | { 56 | return [self payloadObjectForKey:@"device_name"]; 57 | } 58 | 59 | - (void)setDeviceName:(NSString *)deviceName 60 | { 61 | [self setPayloadObject:deviceName forKey:@"device_name"]; 62 | } 63 | 64 | - (NSString *)libVersion 65 | { 66 | return [self payloadObjectForKey:@"device_name"]; 67 | } 68 | 69 | - (void)setLibVersion:(NSString *)libVersion 70 | { 71 | [self setPayloadObject:libVersion forKey:@"lib_version"]; 72 | } 73 | 74 | - (NSString *)deviceModel 75 | { 76 | return [self payloadObjectForKey:@"device_model"]; 77 | } 78 | 79 | - (void)setDeviceModel:(NSString *)deviceModel 80 | { 81 | [self setPayloadObject:deviceModel forKey:@"device_model"]; 82 | } 83 | 84 | - (NSArray *)availableFontFamilies 85 | { 86 | return [self payloadObjectForKey:@"available_font_families"]; 87 | } 88 | 89 | - (void)setAvailableFontFamilies:(NSArray *)availableFontFamilies 90 | { 91 | [self setPayloadObject:availableFontFamilies forKey:@"available_font_families"]; 92 | } 93 | 94 | - (NSString *)mainBundleIdentifier 95 | { 96 | return [self payloadObjectForKey:@"main_bundle_identifier"]; 97 | } 98 | 99 | - (void)setMainBundleIdentifier:(NSString *)mainBundleIdentifier 100 | { 101 | [self setPayloadObject:mainBundleIdentifier forKey:@"main_bundle_identifier"]; 102 | } 103 | 104 | - (void)setTweaks:(NSArray *)tweaks 105 | { 106 | [self setPayloadObject:tweaks forKey:@"tweaks"]; 107 | } 108 | 109 | - (NSArray *)tweaks 110 | { 111 | return [self payloadObjectForKey:@"tweaks"]; 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerDisconnectMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPABTestDesignerDisconnectMessage.h 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 29/7/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPAbstractABTestDesignerMessage.h" 10 | 11 | extern NSString *const MPABTestDesignerDisconnectMessageType; 12 | 13 | @interface MPABTestDesignerDisconnectMessage : MPAbstractABTestDesignerMessage 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerDisconnectMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPABTestDesignerDisconnectMessage.m 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 29/7/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPABTestDesignerConnection.h" 10 | #import "MPABTestDesignerDisconnectMessage.h" 11 | #import "MPVariant.h" 12 | 13 | NSString *const MPABTestDesignerDisconnectMessageType = @"disconnect"; 14 | 15 | @implementation MPABTestDesignerDisconnectMessage 16 | 17 | + (instancetype)message 18 | { 19 | return [[self alloc] initWithType:MPABTestDesignerDisconnectMessageType]; 20 | } 21 | 22 | - (NSOperation *)responseCommandWithConnection:(MPABTestDesignerConnection *)connection 23 | { 24 | __weak MPABTestDesignerConnection *weak_connection = connection; 25 | NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 26 | MPABTestDesignerConnection *conn = weak_connection; 27 | 28 | MPVariant *variant = [connection sessionObjectForKey:kSessionVariantKey]; 29 | if(variant) { 30 | dispatch_sync(dispatch_get_main_queue(), ^{ 31 | [variant stop]; 32 | }); 33 | } 34 | 35 | conn.sessionEnded = YES; 36 | [conn close]; 37 | }]; 38 | return operation; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @class MPABTestDesignerConnection; 7 | 8 | @protocol MPABTestDesignerMessage 9 | 10 | @property (nonatomic, copy, readonly) NSString *type; 11 | 12 | - (void)setPayloadObject:(id)object forKey:(NSString *)key; 13 | - (id)payloadObjectForKey:(NSString *)key; 14 | 15 | - (NSData *)JSONData; 16 | 17 | - (NSOperation *)responseCommandWithConnection:(MPABTestDesignerConnection *)connection; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerSnapshotRequestMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPAbstractABTestDesignerMessage.h" 6 | 7 | @class MPObjectSerializerConfig; 8 | 9 | extern NSString *const MPABTestDesignerSnapshotRequestMessageType; 10 | 11 | @interface MPABTestDesignerSnapshotRequestMessage : MPAbstractABTestDesignerMessage 12 | 13 | + (instancetype)message; 14 | 15 | @property (nonatomic, readonly) MPObjectSerializerConfig *configuration; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerSnapshotResponseMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPAbstractABTestDesignerMessage.h" 6 | 7 | @interface MPABTestDesignerSnapshotResponseMessage : MPAbstractABTestDesignerMessage 8 | 9 | + (instancetype)message; 10 | 11 | @property (nonatomic, strong) UIImage *screenshot; 12 | @property (nonatomic, copy) NSDictionary *serializedObjects; 13 | @property (nonatomic, strong, readonly) NSString *imageHash; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerSnapshotResponseMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPABTestDesignerSnapshotResponseMessage.h" 6 | #import "NSData+MPBase64.h" 7 | 8 | @implementation MPABTestDesignerSnapshotResponseMessage 9 | 10 | + (instancetype)message 11 | { 12 | return [[self alloc] initWithType:@"snapshot_response"]; 13 | } 14 | 15 | - (void)setScreenshot:(UIImage *)screenshot 16 | { 17 | id payloadObject = nil; 18 | id imageHash = nil; 19 | if (screenshot) { 20 | NSData *jpegSnapshotImageData = UIImageJPEGRepresentation(screenshot, 0.5); 21 | if (jpegSnapshotImageData) { 22 | payloadObject = [jpegSnapshotImageData mp_base64EncodedString]; 23 | imageHash = [self getImageHash:jpegSnapshotImageData]; 24 | } 25 | } 26 | 27 | _imageHash = imageHash; 28 | [self setPayloadObject:(payloadObject ?: [NSNull null]) forKey:@"screenshot"]; 29 | [self setPayloadObject:(imageHash ?: [NSNull null]) forKey:@"image_hash"]; 30 | } 31 | 32 | - (UIImage *)screenshot 33 | { 34 | NSString *base64Image = [self payloadObjectForKey:@"screenshot"]; 35 | NSData *imageData = [NSData mp_dataFromBase64String:base64Image]; 36 | 37 | return imageData ? [UIImage imageWithData:imageData] : nil; 38 | } 39 | 40 | - (void)setSerializedObjects:(NSDictionary *)serializedObjects 41 | { 42 | [self setPayloadObject:serializedObjects forKey:@"serialized_objects"]; 43 | } 44 | 45 | - (NSDictionary *)serializedObjects 46 | { 47 | return [self payloadObjectForKey:@"serialized_objects"]; 48 | } 49 | 50 | - (NSString *)getImageHash:(NSData *)imageData 51 | { 52 | unsigned char result[CC_MD5_DIGEST_LENGTH]; 53 | CC_MD5(imageData.bytes, (uint)imageData.length, result); 54 | NSString *imageHash = [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", 55 | result[0], result[1], result[2], result[3], 56 | result[4], result[5], result[6], result[7], 57 | result[8], result[9], result[10], result[11], 58 | result[12], result[13], result[14], result[15]]; 59 | return imageHash; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerTweakRequestMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPABTestDesignerTweakRequestMessage.h 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 7/5/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MPAbstractABTestDesignerMessage.h" 11 | 12 | extern NSString *const MPABTestDesignerTweakRequestMessageType; 13 | 14 | @interface MPABTestDesignerTweakRequestMessage : MPAbstractABTestDesignerMessage 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerTweakRequestMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPABTestDesignerTweakRequestMessage.h 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 7/5/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPABTestDesignerConnection.h" 10 | #import "MPABTestDesignerTweakRequestMessage.h" 11 | #import "MPABTestDesignerTweakResponseMessage.h" 12 | #import "MPLogging.h" 13 | #import "MPVariant.h" 14 | 15 | NSString *const MPABTestDesignerTweakRequestMessageType = @"tweak_request"; 16 | 17 | @implementation MPABTestDesignerTweakRequestMessage 18 | 19 | + (instancetype)message 20 | { 21 | return [[self alloc] initWithType:MPABTestDesignerTweakRequestMessageType]; 22 | } 23 | 24 | - (NSOperation *)responseCommandWithConnection:(MPABTestDesignerConnection *)connection 25 | { 26 | __weak MPABTestDesignerConnection *weak_connection = connection; 27 | NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 28 | MPABTestDesignerConnection *conn = weak_connection; 29 | 30 | MPVariant *variant = [conn sessionObjectForKey:kSessionVariantKey]; 31 | if (!variant) { 32 | variant = [[MPVariant alloc] init]; 33 | [conn setSessionObject:variant forKey:kSessionVariantKey]; 34 | } 35 | 36 | if ([[[self payload] objectForKey:@"tweaks"] isKindOfClass:[NSArray class]]) { 37 | dispatch_sync(dispatch_get_main_queue(), ^{ 38 | [variant addTweaksFromJSONObject:[[self payload] objectForKey:@"tweaks"] andExecute:YES]; 39 | }); 40 | } 41 | 42 | MPABTestDesignerTweakResponseMessage *changeResponseMessage = [MPABTestDesignerTweakResponseMessage message]; 43 | changeResponseMessage.status = @"OK"; 44 | [conn sendMessage:changeResponseMessage]; 45 | }]; 46 | 47 | return operation; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerTweakResponseMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPABTestDesignerTweakResponseMessage.h 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 7/5/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPAbstractABTestDesignerMessage.h" 10 | 11 | @interface MPABTestDesignerTweakResponseMessage : MPAbstractABTestDesignerMessage 12 | 13 | + (instancetype)message; 14 | 15 | @property (nonatomic, copy) NSString *status; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPABTestDesignerTweakResponseMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPABTestDesignerTweakResponseMessage.m 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 7/5/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPABTestDesignerTweakResponseMessage.h" 10 | 11 | @implementation MPABTestDesignerTweakResponseMessage 12 | 13 | + (instancetype)message 14 | { 15 | return [[self alloc] initWithType:@"tweak_response"]; 16 | } 17 | 18 | - (void)setStatus:(NSString *)status 19 | { 20 | [self setPayloadObject:status forKey:@"status"]; 21 | } 22 | 23 | - (NSString *)status 24 | { 25 | return [self payloadObjectForKey:@"status"]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPAbstractABTestDesignerMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPABTestDesignerMessage.h" 6 | 7 | @interface MPAbstractABTestDesignerMessage : NSObject 8 | 9 | @property (nonatomic, copy, readonly) NSString *type; 10 | 11 | + (instancetype)messageWithType:(NSString *)type payload:(NSDictionary *)payload; 12 | 13 | - (id)initWithType:(NSString *)type; 14 | - (id)initWithType:(NSString *)type payload:(NSDictionary *)payload; 15 | 16 | - (void)setPayloadObject:(id)object forKey:(NSString *)key; 17 | - (id)payloadObjectForKey:(NSString *)key; 18 | - (NSDictionary *)payload; 19 | 20 | - (NSData *)JSONData; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPAbstractABTestDesignerMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPAbstractABTestDesignerMessage.h" 5 | #import "MPLogging.h" 6 | 7 | @interface MPAbstractABTestDesignerMessage () 8 | 9 | @property (nonatomic, copy, readwrite) NSString *type; 10 | 11 | @end 12 | 13 | @implementation MPAbstractABTestDesignerMessage 14 | 15 | { 16 | NSMutableDictionary *_payload; 17 | } 18 | 19 | + (instancetype)messageWithType:(NSString *)type payload:(NSDictionary *)payload 20 | { 21 | return [[self alloc] initWithType:type payload:payload]; 22 | } 23 | 24 | - (id)initWithType:(NSString *)type 25 | { 26 | return [self initWithType:type payload:@{}]; 27 | } 28 | 29 | - (id)initWithType:(NSString *)type payload:(NSDictionary *)payload 30 | { 31 | self = [super init]; 32 | if (self) { 33 | _type = type; 34 | _payload = [payload mutableCopy]; 35 | } 36 | 37 | return self; 38 | } 39 | 40 | - (void)setPayloadObject:(id)object forKey:(NSString *)key 41 | { 42 | [_payload setObject:object ?: [NSNull null] forKey:key]; 43 | } 44 | 45 | - (id)payloadObjectForKey:(NSString *)key 46 | { 47 | id object = [_payload objectForKey:key]; 48 | return [object isEqual:[NSNull null]] ? nil : object; 49 | } 50 | 51 | - (NSDictionary *)payload 52 | { 53 | return [_payload copy]; 54 | } 55 | 56 | - (NSData *)JSONData 57 | { 58 | NSDictionary *jsonObject = @{ @"type" : _type, @"payload" : [_payload copy] }; 59 | 60 | NSError *error = nil; 61 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonObject options:0 error:&error]; 62 | if (jsonData == nil && error) { 63 | MixpanelError(@"Failed to serialize test designer message: %@", error); 64 | } 65 | 66 | return jsonData; 67 | } 68 | 69 | - (NSOperation *)responseCommandWithConnection:(MPABTestDesignerConnection *)connection 70 | { 71 | return nil; 72 | } 73 | 74 | - (NSString *)debugDescription 75 | { 76 | return [NSString stringWithFormat:@"<%@:%p type='%@'>", NSStringFromClass([self class]), (__bridge void *)self, self.type]; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPApplicationStateSerializer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @class MPObjectSerializerConfig; 7 | @class MPObjectIdentityProvider; 8 | 9 | @interface MPApplicationStateSerializer : NSObject 10 | 11 | - (id)initWithApplication:(UIApplication *)application configuration:(MPObjectSerializerConfig *)configuration objectIdentityProvider:(MPObjectIdentityProvider *)objectIdentityProvider; 12 | 13 | - (UIImage *)screenshotImageForWindowAtIndex:(NSUInteger)index; 14 | 15 | - (NSDictionary *)objectHierarchyForWindowAtIndex:(NSUInteger)index; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPApplicationStateSerializer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPApplicationStateSerializer.h" 6 | #import "MPClassDescription.h" 7 | #import "MPLogging.h" 8 | #import "MPObjectIdentityProvider.h" 9 | #import "MPObjectSerializer.h" 10 | #import "MPObjectSerializerConfig.h" 11 | 12 | @implementation MPApplicationStateSerializer 13 | 14 | { 15 | MPObjectSerializer *_serializer; 16 | UIApplication *_application; 17 | } 18 | 19 | - (id)initWithApplication:(UIApplication *)application configuration:(MPObjectSerializerConfig *)configuration objectIdentityProvider:(MPObjectIdentityProvider *)objectIdentityProvider 20 | { 21 | NSParameterAssert(application != nil); 22 | NSParameterAssert(configuration != nil); 23 | 24 | self = [super init]; 25 | if (self) { 26 | _application = application; 27 | _serializer = [[MPObjectSerializer alloc] initWithConfiguration:configuration objectIdentityProvider:objectIdentityProvider]; 28 | } 29 | 30 | return self; 31 | } 32 | 33 | - (UIImage *)screenshotImageForWindowAtIndex:(NSUInteger)index 34 | { 35 | UIImage *image = nil; 36 | 37 | UIWindow *window = [self windowAtIndex:index]; 38 | if (window) { 39 | UIGraphicsBeginImageContextWithOptions(window.bounds.size, YES, window.screen.scale); 40 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 41 | if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) { 42 | if ([window drawViewHierarchyInRect:window.bounds afterScreenUpdates:NO] == NO) { 43 | MixpanelError(@"Unable to get complete screenshot for window at index: %d.", (int)index); 44 | } 45 | } else { 46 | [window.layer renderInContext:UIGraphicsGetCurrentContext()]; 47 | } 48 | #else 49 | [window.layer renderInContext:UIGraphicsGetCurrentContext()]; 50 | #endif 51 | image = UIGraphicsGetImageFromCurrentImageContext(); 52 | UIGraphicsEndImageContext(); 53 | } 54 | 55 | return image; 56 | } 57 | 58 | - (UIWindow *)windowAtIndex:(NSUInteger)index 59 | { 60 | NSParameterAssert(index < [_application.windows count]); 61 | return _application.windows[index]; 62 | } 63 | 64 | - (NSDictionary *)objectHierarchyForWindowAtIndex:(NSUInteger)index 65 | { 66 | UIWindow *window = [self windowAtIndex:index]; 67 | if (window) { 68 | return [_serializer serializedObjectsWithRootObject:window]; 69 | } 70 | 71 | return @{}; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPBOOLToNSNumberValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPBOOLToNSNumberValueTransformer 7 | 8 | + (Class)transformedValueClass 9 | { 10 | return [@YES class]; 11 | } 12 | 13 | + (BOOL)allowsReverseTransformation 14 | { 15 | return NO; 16 | } 17 | 18 | - (id)transformedValue:(id)value 19 | { 20 | if ([value respondsToSelector:@selector(boolValue)]) { 21 | return [value boolValue] ? @YES : @NO; 22 | } 23 | 24 | return nil; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPCATransform3DToNSDictionaryValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | static NSDictionary *MPCATransform3DCreateDictionaryRepresentation(CATransform3D transform) 7 | { 8 | return @{ 9 | @"m11" : @(transform.m11), 10 | @"m12" : @(transform.m12), 11 | @"m13" : @(transform.m13), 12 | @"m14" : @(transform.m14), 13 | 14 | @"m21" : @(transform.m21), 15 | @"m22" : @(transform.m22), 16 | @"m23" : @(transform.m23), 17 | @"m24" : @(transform.m24), 18 | 19 | @"m31" : @(transform.m31), 20 | @"m32" : @(transform.m32), 21 | @"m33" : @(transform.m33), 22 | @"m34" : @(transform.m34), 23 | 24 | @"m41" : @(transform.m41), 25 | @"m42" : @(transform.m42), 26 | @"m43" : @(transform.m43), 27 | @"m44" : @(transform.m44), 28 | }; 29 | } 30 | 31 | static BOOL MPCATransform3DMakeWithDictionaryRepresentation(NSDictionary *dictionary, CATransform3D *transform) 32 | { 33 | if (transform) { 34 | id m11 = dictionary[@"m11"]; 35 | id m12 = dictionary[@"m12"]; 36 | id m13 = dictionary[@"m13"]; 37 | id m14 = dictionary[@"m14"]; 38 | 39 | id m21 = dictionary[@"m21"]; 40 | id m22 = dictionary[@"m22"]; 41 | id m23 = dictionary[@"m23"]; 42 | id m24 = dictionary[@"m24"]; 43 | 44 | id m31 = dictionary[@"m31"]; 45 | id m32 = dictionary[@"m32"]; 46 | id m33 = dictionary[@"m33"]; 47 | id m34 = dictionary[@"m34"]; 48 | 49 | id m41 = dictionary[@"m41"]; 50 | id m42 = dictionary[@"m42"]; 51 | id m43 = dictionary[@"m43"]; 52 | id m44 = dictionary[@"m44"]; 53 | 54 | if (m11 && m12 && m13 && m14 && 55 | m21 && m22 && m23 && m24 && 56 | m31 && m32 && m33 && m34 && 57 | m41 && m42 && m43 && m44) 58 | { 59 | transform->m11 = (CGFloat)[m11 doubleValue]; 60 | transform->m12 = (CGFloat)[m12 doubleValue]; 61 | transform->m13 = (CGFloat)[m13 doubleValue]; 62 | transform->m14 = (CGFloat)[m14 doubleValue]; 63 | 64 | transform->m21 = (CGFloat)[m21 doubleValue]; 65 | transform->m22 = (CGFloat)[m22 doubleValue]; 66 | transform->m23 = (CGFloat)[m23 doubleValue]; 67 | transform->m24 = (CGFloat)[m24 doubleValue]; 68 | 69 | transform->m31 = (CGFloat)[m31 doubleValue]; 70 | transform->m32 = (CGFloat)[m32 doubleValue]; 71 | transform->m33 = (CGFloat)[m33 doubleValue]; 72 | transform->m34 = (CGFloat)[m34 doubleValue]; 73 | 74 | transform->m41 = (CGFloat)[m41 doubleValue]; 75 | transform->m42 = (CGFloat)[m42 doubleValue]; 76 | transform->m43 = (CGFloat)[m43 doubleValue]; 77 | transform->m44 = (CGFloat)[m44 doubleValue]; 78 | 79 | return YES; 80 | } 81 | } 82 | 83 | return NO; 84 | } 85 | 86 | @implementation MPCATransform3DToNSDictionaryValueTransformer 87 | 88 | + (Class)transformedValueClass 89 | { 90 | return [NSDictionary class]; 91 | } 92 | 93 | + (BOOL)allowsReverseTransformation 94 | { 95 | return YES; 96 | } 97 | 98 | - (id)transformedValue:(id)value 99 | { 100 | if ([value respondsToSelector:@selector(CATransform3DValue)]) { 101 | return MPCATransform3DCreateDictionaryRepresentation([value CATransform3DValue]); 102 | } 103 | 104 | return @{}; 105 | } 106 | 107 | - (id)reverseTransformedValue:(id)value 108 | { 109 | CATransform3D transform = CATransform3DIdentity; 110 | if ([value isKindOfClass:[NSDictionary class]] && MPCATransform3DMakeWithDictionaryRepresentation(value, &transform)) { 111 | return [NSValue valueWithCATransform3D:transform]; 112 | } 113 | 114 | return [NSValue valueWithCATransform3D:CATransform3DIdentity]; 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPCGAffineTransformToNSDictionaryValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | static NSDictionary *MPCGAffineTransformCreateDictionaryRepresentation(CGAffineTransform transform) 7 | { 8 | return @{ 9 | @"a" : @(transform.a), 10 | @"b" : @(transform.b), 11 | @"c" : @(transform.c), 12 | @"d" : @(transform.d), 13 | @"tx" : @(transform.tx), 14 | @"ty" : @(transform.ty) 15 | }; 16 | } 17 | 18 | static BOOL MPCGAffineTransformMakeWithDictionaryRepresentation(NSDictionary *dictionary, CGAffineTransform *transform) 19 | { 20 | if (transform) { 21 | id a = dictionary[@"a"]; 22 | id b = dictionary[@"b"]; 23 | id c = dictionary[@"c"]; 24 | id d = dictionary[@"d"]; 25 | id tx = dictionary[@"tx"]; 26 | id ty = dictionary[@"ty"]; 27 | 28 | if (a && b && c && d && tx && ty) { 29 | transform->a = (CGFloat)[a doubleValue]; 30 | transform->b = (CGFloat)[b doubleValue]; 31 | transform->c = (CGFloat)[c doubleValue]; 32 | transform->d = (CGFloat)[d doubleValue]; 33 | transform->tx = (CGFloat)[tx doubleValue]; 34 | transform->ty = (CGFloat)[ty doubleValue]; 35 | 36 | return YES; 37 | } 38 | } 39 | 40 | return NO; 41 | } 42 | 43 | @implementation MPCGAffineTransformToNSDictionaryValueTransformer 44 | 45 | + (Class)transformedValueClass 46 | { 47 | return [NSDictionary class]; 48 | } 49 | 50 | + (BOOL)allowsReverseTransformation 51 | { 52 | return YES; 53 | } 54 | 55 | - (id)transformedValue:(id)value 56 | { 57 | if ([value respondsToSelector:@selector(CGAffineTransformValue)]) { 58 | return MPCGAffineTransformCreateDictionaryRepresentation([value CGAffineTransformValue]); 59 | } 60 | 61 | return @{}; 62 | } 63 | 64 | - (id)reverseTransformedValue:(id)value 65 | { 66 | CGAffineTransform transform = CGAffineTransformIdentity; 67 | if ([value isKindOfClass:[NSDictionary class]] && MPCGAffineTransformMakeWithDictionaryRepresentation(value, &transform)) { 68 | return [NSValue valueWithCGAffineTransform:transform]; 69 | } 70 | 71 | return [NSValue valueWithCGAffineTransform:CGAffineTransformIdentity]; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPCGColorRefToNSStringValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPCGColorRefToNSStringValueTransformer 7 | 8 | + (Class)transformedValueClass 9 | { 10 | return [NSString class]; 11 | } 12 | 13 | - (id)transformedValue:(id)value 14 | { 15 | if (value && CFGetTypeID((__bridge CFTypeRef)value) == CGColorGetTypeID()) { 16 | NSValueTransformer *transformer = [NSValueTransformer valueTransformerForName:@"MPUIColorToNSStringValueTransformer"]; 17 | return [transformer transformedValue:[[UIColor alloc] initWithCGColor:(__bridge CGColorRef)value]]; 18 | } 19 | 20 | return nil; 21 | } 22 | 23 | - (id)reverseTransformedValue:(id)value 24 | { 25 | NSValueTransformer *transformer = [NSValueTransformer valueTransformerForName:@"MPUIColorToNSStringValueTransformer"]; 26 | UIColor *uiColor = [transformer reverseTransformedValue:value]; 27 | return CFBridgingRelease(CGColorCreateCopy([uiColor CGColor])); 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPCGPointToNSDictionaryValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPCGPointToNSDictionaryValueTransformer 7 | 8 | + (Class)transformedValueClass 9 | { 10 | return [NSDictionary class]; 11 | } 12 | 13 | + (BOOL)allowsReverseTransformation 14 | { 15 | return YES; 16 | } 17 | 18 | - (id)transformedValue:(id)value 19 | { 20 | if ([value respondsToSelector:@selector(CGPointValue)]) { 21 | CGPoint point = [value CGPointValue]; 22 | point.x = isnormal(point.x) ? point.x : 0.0f; 23 | point.y = isnormal(point.y) ? point.y : 0.0f; 24 | return CFBridgingRelease(CGPointCreateDictionaryRepresentation(point)); 25 | } 26 | 27 | return nil; 28 | } 29 | 30 | - (id)reverseTransformedValue:(id)value 31 | { 32 | CGPoint point = CGPointZero; 33 | if ([value isKindOfClass:[NSDictionary class]] && CGPointMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)value, &point)) { 34 | return [NSValue valueWithCGPoint:point]; 35 | } 36 | 37 | return [NSValue valueWithCGPoint:CGPointZero]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPCGRectToNSDictionaryValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPCGRectToNSDictionaryValueTransformer 7 | 8 | + (Class)transformedValueClass 9 | { 10 | return [NSDictionary class]; 11 | } 12 | 13 | + (BOOL)allowsReverseTransformation 14 | { 15 | return YES; 16 | } 17 | 18 | - (id)transformedValue:(id)value 19 | { 20 | if ([value respondsToSelector:@selector(CGRectValue)]) { 21 | CGRect rect = [value CGRectValue]; 22 | rect.origin.x = isnormal(rect.origin.x) ? rect.origin.x : 0.0f; 23 | rect.origin.y = isnormal(rect.origin.y) ? rect.origin.y : 0.0f; 24 | rect.size.width = isnormal(rect.size.width) ? rect.size.width : 0.0f; 25 | rect.size.height = isnormal(rect.size.height) ? rect.size.height : 0.0f; 26 | return CFBridgingRelease(CGRectCreateDictionaryRepresentation(rect)); 27 | } 28 | 29 | return nil; 30 | } 31 | 32 | - (id)reverseTransformedValue:(id)value 33 | { 34 | CGRect rect = CGRectZero; 35 | if ([value isKindOfClass:[NSDictionary class]] && CGRectMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)value, &rect)) { 36 | return [NSValue valueWithCGRect:rect]; 37 | } 38 | 39 | return [NSValue valueWithCGRect:CGRectZero]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPCGSizeToNSDictionaryValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPCGSizeToNSDictionaryValueTransformer 7 | 8 | + (Class)transformedValueClass 9 | { 10 | return [NSDictionary class]; 11 | } 12 | 13 | + (BOOL)allowsReverseTransformation 14 | { 15 | return YES; 16 | } 17 | 18 | - (id)transformedValue:(id)value 19 | { 20 | if ([value respondsToSelector:@selector(CGSizeValue)]) { 21 | CGSize size = [value CGSizeValue]; 22 | size.width = isnormal(size.width) ? size.width : 0.0f; 23 | size.height = isnormal(size.height) ? size.height : 0.0f; 24 | return CFBridgingRelease(CGSizeCreateDictionaryRepresentation(size)); 25 | } 26 | 27 | return nil; 28 | } 29 | 30 | - (id)reverseTransformedValue:(id)value 31 | { 32 | CGSize size = CGSizeZero; 33 | if ([value isKindOfClass:[NSDictionary class]] && CGSizeMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)value, &size)) { 34 | return [NSValue valueWithCGSize:size]; 35 | } 36 | 37 | return [NSValue valueWithCGSize:CGSizeZero]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPCategoryHelpers.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import 4 | 5 | @interface UIView (MPHelpers) 6 | 7 | - (UIImage *)mp_snapshotImage; 8 | - (UIImage *)mp_snapshotForBlur; 9 | - (int)mp_fingerprintVersion; 10 | 11 | @end 12 | 13 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPClassDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPTypeDescription.h" 6 | 7 | @interface MPClassDescription : MPTypeDescription 8 | 9 | @property (nonatomic, readonly) MPClassDescription *superclassDescription; 10 | @property (nonatomic, readonly) NSArray *propertyDescriptions; 11 | @property (nonatomic, readonly) NSArray *delegateInfos; 12 | 13 | - (id)initWithSuperclassDescription:(MPClassDescription *)superclassDescription dictionary:(NSDictionary *)dictionary; 14 | 15 | - (BOOL)isDescriptionForKindOfClass:(Class)class; 16 | 17 | @end 18 | 19 | @interface MPDelegateInfo : NSObject 20 | 21 | @property (nonatomic, readonly) NSString *selectorName; 22 | 23 | - (id)initWithDictionary:(NSDictionary *)dictionary; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPClassDescription.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPClassDescription.h" 5 | #import "MPPropertyDescription.h" 6 | 7 | @implementation MPDelegateInfo 8 | 9 | - (id)initWithDictionary:(NSDictionary *)dictionary 10 | { 11 | if (self = [super init]) { 12 | _selectorName = dictionary[@"selector"]; 13 | } 14 | return self; 15 | } 16 | 17 | @end 18 | 19 | @implementation MPClassDescription 20 | 21 | { 22 | NSArray *_propertyDescriptions; 23 | NSArray *_delegateInfos; 24 | } 25 | 26 | - (id)initWithSuperclassDescription:(MPClassDescription *)superclassDescription dictionary:(NSDictionary *)dictionary 27 | { 28 | self = [super initWithDictionary:dictionary]; 29 | if (self) { 30 | _superclassDescription = superclassDescription; 31 | 32 | NSMutableArray *propertyDescriptions = [NSMutableArray array]; 33 | for (NSDictionary *propertyDictionary in dictionary[@"properties"]) { 34 | [propertyDescriptions addObject:[[MPPropertyDescription alloc] initWithDictionary:propertyDictionary]]; 35 | } 36 | 37 | _propertyDescriptions = [propertyDescriptions copy]; 38 | 39 | NSMutableArray *delegateInfos = [NSMutableArray array]; 40 | for (NSDictionary *delegateInfoDictionary in dictionary[@"delegateImplements"]) { 41 | [delegateInfos addObject:[[MPDelegateInfo alloc] initWithDictionary:delegateInfoDictionary]]; 42 | } 43 | _delegateInfos = [delegateInfos copy]; 44 | } 45 | 46 | return self; 47 | } 48 | 49 | - (NSArray *)propertyDescriptions 50 | { 51 | NSMutableDictionary *allPropertyDescriptions = [[NSMutableDictionary alloc] init]; 52 | 53 | MPClassDescription *description = self; 54 | while (description) 55 | { 56 | for (MPPropertyDescription *propertyDescription in description->_propertyDescriptions) { 57 | if (!allPropertyDescriptions[propertyDescription.name]) { 58 | allPropertyDescriptions[propertyDescription.name] = propertyDescription; 59 | } 60 | } 61 | description = description.superclassDescription; 62 | } 63 | 64 | return [allPropertyDescriptions allValues]; 65 | } 66 | 67 | - (BOOL)isDescriptionForKindOfClass:(Class)class 68 | { 69 | return [self.name isEqualToString:NSStringFromClass(class)] && [self.superclassDescription isDescriptionForKindOfClass:[class superclass]]; 70 | } 71 | 72 | - (NSString *)debugDescription 73 | { 74 | return [NSString stringWithFormat:@"<%@:%p name='%@' superclass='%@'>", NSStringFromClass([self class]), (__bridge void *)self, self.name, self.superclassDescription ? self.superclassDescription.name : @""]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPCloseBtn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/MPCloseBtn.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPCloseBtn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/MPCloseBtn@2x.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPDesignerEventBindingMessage.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPDesignerEventBindingMessage.h 3 | // HelloMixpanel 4 | // 5 | // Created by Amanda Canyon on 11/18/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPAbstractABTestDesignerMessage.h" 10 | 11 | extern NSString *const MPDesignerEventBindingRequestMessageType; 12 | 13 | @interface MPDesignerEventBindingRequestMesssage : MPAbstractABTestDesignerMessage 14 | 15 | @end 16 | 17 | 18 | @interface MPDesignerEventBindingResponseMesssage : MPAbstractABTestDesignerMessage 19 | 20 | + (instancetype)message; 21 | 22 | @property (nonatomic, copy) NSString *status; 23 | 24 | @end 25 | 26 | 27 | @interface MPDesignerTrackMessage : MPAbstractABTestDesignerMessage 28 | 29 | + (instancetype)message; 30 | + (instancetype)messageWithPayload:(NSDictionary *)payload; 31 | 32 | @end 33 | 34 | 35 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPDesignerEventBindingRequestMesssage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPDesignerEventBindingRequestMesssage.m 3 | // HelloMixpanel 4 | // 5 | // Created by Amanda Canyon on 7/15/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "Mixpanel.h" 10 | #import "MPABTestDesignerConnection.h" 11 | #import "MPDesignerEventBindingMessage.h" 12 | #import "MPDesignerSessionCollection.h" 13 | #import "MPEventBinding.h" 14 | #import "MPObjectSelector.h" 15 | #import "MPSwizzler.h" 16 | 17 | NSString *const MPDesignerEventBindingRequestMessageType = @"event_binding_request"; 18 | 19 | @interface MPEventBindingCollection : NSObject 20 | 21 | @property (nonatomic) NSMutableArray *bindings; 22 | 23 | @end 24 | 25 | @implementation MPEventBindingCollection 26 | 27 | - (void)updateBindings:(NSArray *)bindingPayload 28 | { 29 | NSMutableArray *newBindings = [NSMutableArray array]; 30 | for (NSDictionary *bindingInfo in bindingPayload) { 31 | MPEventBinding *binding = [MPEventBinding bindngWithJSONObject:bindingInfo]; 32 | [newBindings addObject:binding]; 33 | } 34 | 35 | if (self.bindings) { 36 | for (MPEventBinding *oldBinding in self.bindings) { 37 | [oldBinding stop]; 38 | } 39 | } 40 | self.bindings = newBindings; 41 | for (MPEventBinding *newBinding in self.bindings) { 42 | [newBinding execute]; 43 | } 44 | } 45 | 46 | - (void)cleanup 47 | { 48 | if (self.bindings) { 49 | for (MPEventBinding *oldBinding in self.bindings) { 50 | [oldBinding stop]; 51 | } 52 | } 53 | self.bindings = nil; 54 | } 55 | 56 | @end 57 | 58 | @implementation MPDesignerEventBindingRequestMesssage 59 | 60 | + (instancetype)message 61 | { 62 | return [[self alloc] initWithType:@"event_binding_request"]; 63 | } 64 | 65 | - (NSOperation *)responseCommandWithConnection:(MPABTestDesignerConnection *)connection 66 | { 67 | __weak MPABTestDesignerConnection *weak_connection = connection; 68 | NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ 69 | MPABTestDesignerConnection *conn = weak_connection; 70 | 71 | dispatch_sync(dispatch_get_main_queue(), ^{ 72 | NSLog(@"Loading event bindings:\n%@",[[self payload] objectForKey:@"events"]); 73 | NSArray *payload = [[self payload] objectForKey:@"events"]; 74 | MPEventBindingCollection *bindingCollection = [conn sessionObjectForKey:@"event_bindings"]; 75 | if (!bindingCollection) { 76 | bindingCollection = [[MPEventBindingCollection alloc] init]; 77 | [conn setSessionObject:bindingCollection forKey:@"event_bindings"]; 78 | } 79 | [bindingCollection updateBindings:payload]; 80 | }); 81 | 82 | MPDesignerEventBindingResponseMesssage *changeResponseMessage = [MPDesignerEventBindingResponseMesssage message]; 83 | changeResponseMessage.status = @"OK"; 84 | [conn sendMessage:changeResponseMessage]; 85 | }]; 86 | 87 | return operation; 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPDesignerEventBindingResponseMesssage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPDesignerEventBindingResponseMesssage.m 3 | // HelloMixpanel 4 | // 5 | // Created by Amanda Canyon on 7/15/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPDesignerEventBindingMessage.h" 10 | 11 | @implementation MPDesignerEventBindingResponseMesssage 12 | 13 | + (instancetype)message 14 | { 15 | return [[self alloc] initWithType:@"event_binding_response"]; 16 | } 17 | 18 | - (void)setStatus:(NSString *)status 19 | { 20 | [self setPayloadObject:status forKey:@"status"]; 21 | } 22 | 23 | - (NSString *)status 24 | { 25 | return [self payloadObjectForKey:@"status"]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPDesignerSessionCollection.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPDesignerSessionCollection.h 3 | // HelloMixpanel 4 | // 5 | // Created by Amanda Canyon on 8/22/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol MPDesignerSessionCollection 12 | 13 | - (void)cleanup; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPDesignerTrackMessage.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPDesignerTrackMessage.m 3 | // HelloMixpanel 4 | // 5 | // Created by Amanda Canyon on 9/3/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPDesignerEventBindingMessage.h" 10 | 11 | @implementation MPDesignerTrackMessage 12 | 13 | { 14 | NSDictionary *_payload; 15 | } 16 | 17 | + (instancetype)message 18 | { 19 | return [[self alloc] initWithType:@"track_message"]; 20 | } 21 | 22 | + (instancetype)messageWithPayload:(NSDictionary *)payload 23 | { 24 | return[[self alloc] initWithType:@"track_message" andPayload:payload]; 25 | } 26 | 27 | - (id)initWithType:(NSString *)type 28 | { 29 | return [self initWithType:type andPayload:@{}]; 30 | } 31 | 32 | - (id)initWithType:(NSString *)type andPayload:(NSDictionary *)payload 33 | { 34 | if (self = [super initWithType:type]) { 35 | _payload = payload; 36 | } 37 | return self; 38 | } 39 | 40 | - (NSData *)JSONData 41 | { 42 | NSDictionary *jsonObject = @{ @"type" : self.type, @"payload" : [_payload copy] }; 43 | 44 | NSError *error = nil; 45 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonObject options:0 error:&error]; 46 | if (error) { 47 | NSLog(@"Failed to serialize test designer message: %@", error); 48 | } 49 | 50 | return jsonData; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPEnumDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPTypeDescription.h" 6 | 7 | @interface MPEnumDescription : MPTypeDescription 8 | 9 | @property (nonatomic, assign, getter=isFlagsSet, readonly) BOOL flagSet; 10 | @property (nonatomic, copy, readonly) NSString *baseType; 11 | 12 | - (NSArray *)allValues; // array of NSNumber instances 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPEnumDescription.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPEnumDescription.h" 5 | 6 | @implementation MPEnumDescription 7 | 8 | { 9 | NSMutableDictionary *_values; 10 | } 11 | 12 | - (id)initWithDictionary:(NSDictionary *)dictionary 13 | { 14 | NSParameterAssert(dictionary[@"flag_set"] != nil); 15 | NSParameterAssert(dictionary[@"base_type"] != nil); 16 | NSParameterAssert(dictionary[@"values"] != nil); 17 | 18 | self = [super initWithDictionary:dictionary]; 19 | if (self) { 20 | _flagSet = [dictionary[@"flag_set"] boolValue]; 21 | _baseType = [dictionary[@"base_type"] copy]; 22 | _values = [[NSMutableDictionary alloc] init]; 23 | 24 | for (NSDictionary *value in dictionary[@"values"]) { 25 | _values[value[@"value"]] = value[@"display_name"]; 26 | } 27 | } 28 | 29 | return self; 30 | } 31 | 32 | - (NSArray *)allValues 33 | { 34 | return [_values allKeys]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPEventBinding.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPEventBinding.h 3 | // HelloMixpanel 4 | // 5 | // Created by Amanda Canyon on 7/22/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MPObjectSelector.h" 11 | 12 | @interface MPEventBinding : NSObject 13 | 14 | @property (nonatomic) NSUInteger ID; 15 | @property (nonatomic) NSString *name; 16 | @property (nonatomic) MPObjectSelector *path; 17 | @property (nonatomic) NSString *eventName; 18 | 19 | @property (nonatomic, assign) Class swizzleClass; 20 | 21 | /*! 22 | @property 23 | 24 | @abstract 25 | Whether this specific binding is currently running on the device. 26 | 27 | @discussion 28 | This property will not be restored on unarchive, as the binding will need 29 | to be run again once the app is restarted. 30 | */ 31 | @property (nonatomic) BOOL running; 32 | 33 | + (id)bindngWithJSONObject:(id)object; 34 | 35 | - (instancetype)init __unavailable; 36 | - (id)initWithEventName:(NSString *)eventName onPath:(NSString *)path; 37 | 38 | /*! 39 | Intercepts track calls and adds a property indicating the track event 40 | was from a binding 41 | */ 42 | + (void)track:(NSString *)event properties:(NSDictionary *)properties; 43 | /*! 44 | Method stubs. Implement them in subclasses 45 | */ 46 | + (NSString *)typeName; 47 | - (void)execute; 48 | - (void)stop; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPEventBinding.m: -------------------------------------------------------------------------------- 1 | // 2 | // MPEventBinding.m 3 | // HelloMixpanel 4 | // 5 | // Created by Amanda Canyon on 7/22/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "Mixpanel.h" 10 | #import "MPEventBinding.h" 11 | #import "MPUIControlBinding.h" 12 | #import "MPUITableViewBinding.h" 13 | 14 | @implementation MPEventBinding 15 | 16 | + (MPEventBinding *)bindngWithJSONObject:(NSDictionary *)object 17 | { 18 | if (object == nil) { 19 | NSLog(@"must supply an JSON object to initialize from"); 20 | return nil; 21 | } 22 | 23 | NSString *bindingType = [object objectForKey:@"event_type"]; 24 | Class klass = [self subclassFromString:bindingType]; 25 | return [klass bindngWithJSONObject:object]; 26 | } 27 | 28 | + (Class)subclassFromString:(NSString *)bindingType 29 | { 30 | NSDictionary *classTypeMap = @{ 31 | [MPUIControlBinding typeName] : [MPUIControlBinding class], 32 | [MPUITableViewBinding typeName] : [MPUITableViewBinding class] 33 | }; 34 | return[classTypeMap valueForKey:bindingType] ?: [MPUIControlBinding class]; 35 | } 36 | 37 | + (void)track:(NSString *)event properties:(NSDictionary *)properties 38 | { 39 | NSMutableDictionary *bindingProperties = [[NSMutableDictionary alloc] initWithObjectsAndKeys: @YES, @"$from_binding", nil]; 40 | [bindingProperties addEntriesFromDictionary:properties]; 41 | [[Mixpanel sharedInstance] track:event properties:bindingProperties]; 42 | } 43 | 44 | - (id)initWithEventName:(NSString *)eventName onPath:(NSString *)path 45 | { 46 | if (self = [super init]) { 47 | self.eventName = eventName; 48 | self.path = [[MPObjectSelector alloc] initWithString:path]; 49 | self.name = [[NSUUID UUID] UUIDString]; 50 | self.running = false; 51 | } 52 | return self; 53 | } 54 | 55 | - (NSString *)description 56 | { 57 | return [NSString stringWithFormat:@"Event Binding base class: '%@' for '%@'", [self eventName], [self path]]; 58 | } 59 | 60 | #pragma mark -- Method stubs 61 | 62 | + (NSString *)typeName 63 | { 64 | @throw [NSException exceptionWithName:NSInternalInconsistencyException 65 | reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)] 66 | userInfo:nil]; 67 | } 68 | 69 | - (void)execute 70 | { 71 | @throw [NSException exceptionWithName:NSInternalInconsistencyException 72 | reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)] 73 | userInfo:nil]; 74 | } 75 | 76 | - (void)stop 77 | { 78 | @throw [NSException exceptionWithName:NSInternalInconsistencyException 79 | reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)] 80 | userInfo:nil]; 81 | } 82 | 83 | #pragma mark -- NSCoder 84 | 85 | - (id)initWithCoder:(NSCoder *)aDecoder 86 | { 87 | NSString *path = (NSString *)[MPObjectSelector objectSelectorWithString:[aDecoder decodeObjectForKey:@"path"]]; 88 | NSString *eventName = (NSString *)[aDecoder decodeObjectForKey:@"eventName"]; 89 | if (self = [self initWithEventName:eventName onPath:path]) { 90 | self.ID = [(NSNumber *)[aDecoder decodeObjectForKey:@"ID"] unsignedLongValue]; 91 | self.name = [aDecoder decodeObjectForKey:@"name"]; 92 | self.swizzleClass = NSClassFromString([aDecoder decodeObjectForKey:@"swizzleClass"]); 93 | } 94 | return self; 95 | } 96 | 97 | - (void)encodeWithCoder:(NSCoder *)aCoder 98 | { 99 | [aCoder encodeObject:[NSNumber numberWithUnsignedLong:_ID] forKey:@"ID"]; 100 | [aCoder encodeObject:_name forKey:@"name"]; 101 | [aCoder encodeObject:_path.string forKey:@"path"]; 102 | [aCoder encodeObject:_eventName forKey:@"eventName"]; 103 | [aCoder encodeObject:NSStringFromClass(_swizzleClass) forKey:@"swizzleClass"]; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPLogging.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPLogging.h 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 7/11/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #ifndef HelloMixpanel_MPLogging_h 10 | #define HelloMixpanel_MPLogging_h 11 | 12 | static inline void MPLog(NSString *format, ...) { 13 | __block va_list arg_list; 14 | va_start (arg_list, format); 15 | NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:arg_list]; 16 | va_end(arg_list); 17 | NSLog(@"[Mixpanel] %@", formattedString); 18 | } 19 | 20 | #ifdef MIXPANEL_ERROR 21 | #define MixpanelError(...) MPLog(__VA_ARGS__) 22 | #else 23 | #define MixpanelError(...) 24 | #endif 25 | 26 | #ifdef MIXPANEL_DEBUG 27 | #define MixpanelDebug(...) MPLog(__VA_ARGS__) 28 | #else 29 | #define MixpanelDebug(...) 30 | #endif 31 | 32 | #ifdef MIXPANEL_MESSAGING_DEBUG 33 | #define MessagingDebug(...) MPLog(__VA_ARGS__) 34 | #else 35 | #define MessagingDebug(...) 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPNSAttributedStringToNSDictionaryValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPLogging.h" 5 | #import "MPValueTransformers.h" 6 | 7 | @implementation MPNSAttributedStringToNSDictionaryValueTransformer 8 | 9 | + (Class)transformedValueClass 10 | { 11 | return [NSDictionary class]; 12 | } 13 | 14 | + (BOOL)allowsReverseTransformation 15 | { 16 | return YES; 17 | } 18 | 19 | - (id)transformedValue:(id)value 20 | { 21 | if ([value isKindOfClass:[NSAttributedString class]]) { 22 | NSAttributedString *attributedString = value; 23 | 24 | NSError *error = nil; 25 | NSData *data = nil; 26 | 27 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 28 | if ([attributedString respondsToSelector:@selector(dataFromRange:documentAttributes:error:)]) { 29 | data = [attributedString dataFromRange:NSMakeRange(0, [attributedString length]) 30 | documentAttributes:@{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType} 31 | error:&error]; 32 | } 33 | #endif 34 | if (data) { 35 | return @{ 36 | @"mime_type" : @"text/html", 37 | @"data" : [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] 38 | }; 39 | } else { 40 | MixpanelError(@"Failed to convert NSAttributedString to HTML: %@", error); 41 | } 42 | } 43 | 44 | return nil; 45 | } 46 | 47 | - (id)reverseTransformedValue:(id)value 48 | { 49 | if ([value isKindOfClass:[NSDictionary class]]) { 50 | NSDictionary *dictionaryValue = value; 51 | NSString *mimeType = dictionaryValue[@"mime_type"]; 52 | NSString *dataString = dictionaryValue[@"data"]; 53 | 54 | if ([mimeType isEqualToString:@"text/html"] && dataString) { 55 | NSError *error = nil; 56 | NSAttributedString *attributedString; 57 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 58 | NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding]; 59 | attributedString = [[NSAttributedString alloc] initWithData:data 60 | options:@{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType} 61 | documentAttributes:NULL 62 | error:&error]; 63 | #endif 64 | if (attributedString == nil) { 65 | MixpanelError(@"Failed to convert HTML to NSAttributed string: %@", error); 66 | } 67 | 68 | return attributedString; 69 | } 70 | } 71 | 72 | return nil; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPNSNumberToCGFloatValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPNSNumberToCGFloatValueTransformer 7 | 8 | + (Class)transformedValueClass 9 | { 10 | return [NSNumber class]; 11 | } 12 | 13 | + (BOOL)allowsReverseTransformation 14 | { 15 | return NO; 16 | } 17 | 18 | - (id)transformedValue:(id)value 19 | { 20 | if ([value isKindOfClass:[NSNumber class]]) { 21 | NSNumber *number = (NSNumber *) value; 22 | 23 | // if the number is not a cgfloat, cast it to a cgfloat 24 | if (strcmp([number objCType], (char *) @encode(CGFloat)) != 0) { 25 | if (strcmp((char *) @encode(CGFloat), (char *) @encode(double)) == 0) { 26 | value = [NSNumber numberWithDouble:[number doubleValue]]; 27 | } else { 28 | value = [NSNumber numberWithFloat:[number floatValue]]; 29 | } 30 | } 31 | 32 | return value; 33 | } 34 | 35 | return nil; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPNotification.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface MPNotification : NSObject 4 | 5 | extern NSString *const MPNotificationTypeMini; 6 | extern NSString *const MPNotificationTypeTakeover; 7 | 8 | @property (nonatomic, readonly) NSUInteger ID; 9 | @property (nonatomic, readonly) NSUInteger messageID; 10 | @property (nonatomic, strong) NSString *type; 11 | @property (nonatomic, strong) NSURL *imageURL; 12 | @property (nonatomic, strong) NSData *image; 13 | @property (nonatomic, strong) NSString *title; 14 | @property (nonatomic, strong) NSString *body; 15 | @property (nonatomic, strong) NSString *callToAction; 16 | @property (nonatomic, strong) NSURL *callToActionURL; 17 | 18 | + (MPNotification *)notificationWithJSONObject:(NSDictionary *)object; 19 | 20 | - (instancetype)init __unavailable; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPNotificationViewController.h: -------------------------------------------------------------------------------- 1 | #if ! __has_feature(objc_arc) 2 | #error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag on this file. 3 | #endif 4 | 5 | #import "MPNotification.h" 6 | 7 | @protocol MPNotificationViewControllerDelegate; 8 | 9 | @interface MPNotificationViewController : UIViewController 10 | 11 | @property (nonatomic, strong) MPNotification *notification; 12 | @property (nonatomic, weak) id delegate; 13 | 14 | - (void)hideWithAnimation:(BOOL)animated completion:(void (^)(void))completion; 15 | 16 | @end 17 | 18 | @interface MPTakeoverNotificationViewController : MPNotificationViewController 19 | 20 | @property (nonatomic, strong) UIImage *backgroundImage; 21 | 22 | @end 23 | 24 | @interface MPMiniNotificationViewController : MPNotificationViewController 25 | 26 | - (void)showWithAnimation; 27 | 28 | @end 29 | 30 | @protocol MPNotificationViewControllerDelegate 31 | 32 | - (void)notificationController:(MPNotificationViewController *)controller wasDismissedWithStatus:(BOOL)status; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPObjectIdentifierProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @protocol MPObjectIdentifierProvider 7 | - (NSString *)identifierForObject:(id)object; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPObjectIdentityProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @interface MPObjectIdentityProvider : NSObject 7 | 8 | - (NSString *)identifierForObject:(id)object; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPObjectIdentityProvider.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPObjectIdentityProvider.h" 5 | #import "MPSequenceGenerator.h" 6 | 7 | @implementation MPObjectIdentityProvider 8 | 9 | { 10 | NSMapTable *_objectToIdentifierMap; 11 | MPSequenceGenerator *_sequenceGenerator; 12 | } 13 | 14 | - (id)init 15 | { 16 | self = [super init]; 17 | if (self) { 18 | _objectToIdentifierMap = [NSMapTable weakToStrongObjectsMapTable]; 19 | _sequenceGenerator = [[MPSequenceGenerator alloc] init]; 20 | } 21 | 22 | return self; 23 | } 24 | 25 | - (NSString *)identifierForObject:(id)object 26 | { 27 | if ([object isKindOfClass:[NSString class]]) { 28 | return object; 29 | } 30 | NSString *identifier = [_objectToIdentifierMap objectForKey:object]; 31 | if (identifier == nil) { 32 | identifier = [NSString stringWithFormat:@"$%" PRIi32, [_sequenceGenerator nextValue]]; 33 | [_objectToIdentifierMap setObject:identifier forKey:object]; 34 | } 35 | 36 | return identifier; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPObjectSelector.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjectSelector.h 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 5/5/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MPObjectSelector : NSObject 12 | 13 | @property (nonatomic, strong, readonly) NSString *string; 14 | 15 | + (MPObjectSelector *)objectSelectorWithString:(NSString *)string; 16 | - (id)initWithString:(NSString *)string; 17 | 18 | - (NSArray *)selectFromRoot:(id)root; 19 | - (NSArray *)fuzzySelectFromRoot:(id)root; 20 | 21 | - (BOOL)isLeafSelected:(id)leaf fromRoot:(id)root; 22 | - (BOOL)fuzzyIsLeafSelected:(id)leaf fromRoot:(id)root; 23 | 24 | - (Class)selectedClass; 25 | - (NSString *)description; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPObjectSerializer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @class MPClassDescription; 7 | @class MPObjectSerializerContext; 8 | @class MPObjectSerializerConfig; 9 | @class MPObjectIdentityProvider; 10 | 11 | @interface MPObjectSerializer : NSObject 12 | 13 | /*! 14 | @param An array of MPClassDescription instances. 15 | */ 16 | - (id)initWithConfiguration:(MPObjectSerializerConfig *)configuration objectIdentityProvider:(MPObjectIdentityProvider *)objectIdentityProvider; 17 | 18 | - (NSDictionary *)serializedObjectsWithRootObject:(id)rootObject; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPObjectSerializerConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @class MPEnumDescription; 7 | @class MPClassDescription; 8 | @class MPTypeDescription; 9 | 10 | 11 | @interface MPObjectSerializerConfig : NSObject 12 | 13 | @property (nonatomic, readonly) NSArray *classDescriptions; 14 | @property (nonatomic, readonly) NSArray *enumDescriptions; 15 | 16 | - (id)initWithDictionary:(NSDictionary *)dictionary; 17 | 18 | - (MPTypeDescription *)typeWithName:(NSString *)name; 19 | - (MPEnumDescription *)enumWithName:(NSString *)name; 20 | - (MPClassDescription *)classWithName:(NSString *)name; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPObjectSerializerConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPClassDescription.h" 5 | #import "MPEnumDescription.h" 6 | #import "MPObjectSerializerConfig.h" 7 | #import "MPTypeDescription.h" 8 | 9 | @implementation MPObjectSerializerConfig 10 | 11 | { 12 | NSDictionary *_classes; 13 | NSDictionary *_enums; 14 | } 15 | 16 | - (id)initWithDictionary:(NSDictionary *)dictionary 17 | { 18 | self = [super init]; 19 | if (self) { 20 | NSMutableDictionary *classDescriptions = [[NSMutableDictionary alloc] init]; 21 | for (NSDictionary *d in dictionary[@"classes"]) { 22 | NSString *superclassName = d[@"superclass"]; 23 | MPClassDescription *superclassDescription = superclassName ? classDescriptions[superclassName] : nil; 24 | MPClassDescription *classDescription = [[MPClassDescription alloc] initWithSuperclassDescription:superclassDescription 25 | dictionary:d]; 26 | 27 | [classDescriptions setObject:classDescription forKey:classDescription.name]; 28 | } 29 | 30 | NSMutableDictionary *enumDescriptions = [[NSMutableDictionary alloc] init]; 31 | for (NSDictionary *d in dictionary[@"enums"]) { 32 | MPEnumDescription *enumDescription = [[MPEnumDescription alloc] initWithDictionary:d]; 33 | [enumDescriptions setObject:enumDescription forKey:enumDescription.name]; 34 | } 35 | 36 | _classes = [classDescriptions copy]; 37 | _enums = [enumDescriptions copy]; 38 | } 39 | 40 | return self; 41 | } 42 | 43 | - (NSArray *)classDescriptions 44 | { 45 | return [_classes allValues]; 46 | } 47 | 48 | - (MPEnumDescription *)enumWithName:(NSString *)name 49 | { 50 | return _enums[name]; 51 | } 52 | 53 | - (MPClassDescription *)classWithName:(NSString *)name 54 | { 55 | return _classes[name]; 56 | } 57 | 58 | - (MPTypeDescription *)typeWithName:(NSString *)name 59 | { 60 | MPEnumDescription *enumDescription = [self enumWithName:name]; 61 | if (enumDescription) { 62 | return enumDescription; 63 | } 64 | 65 | MPClassDescription *classDescription = [self classWithName:name]; 66 | if (classDescription) { 67 | return classDescription; 68 | } 69 | 70 | return nil; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPObjectSerializerContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @interface MPObjectSerializerContext : NSObject 7 | 8 | - (id)initWithRootObject:(id)object; 9 | 10 | - (BOOL)hasUnvisitedObjects; 11 | 12 | - (void)enqueueUnvisitedObject:(NSObject *)object; 13 | - (NSObject *)dequeueUnvisitedObject; 14 | 15 | - (void)addVisitedObject:(NSObject *)object; 16 | - (BOOL)isVisitedObject:(NSObject *)object; 17 | 18 | - (void)addSerializedObject:(NSDictionary *)serializedObject; 19 | - (NSArray *)allSerializedObjects; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPObjectSerializerContext.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPObjectSerializerContext.h" 5 | 6 | @implementation MPObjectSerializerContext 7 | 8 | { 9 | NSMutableSet *_visitedObjects; 10 | NSMutableSet *_unvisitedObjects; 11 | NSMutableDictionary *_serializedObjects; 12 | } 13 | 14 | - (id)initWithRootObject:(id)object 15 | { 16 | self = [super init]; 17 | if (self) { 18 | _visitedObjects = [NSMutableSet set]; 19 | _unvisitedObjects = [NSMutableSet setWithObject:object]; 20 | _serializedObjects = [[NSMutableDictionary alloc] init]; 21 | } 22 | 23 | return self; 24 | } 25 | 26 | - (BOOL)hasUnvisitedObjects 27 | { 28 | return [_unvisitedObjects count] > 0; 29 | } 30 | 31 | - (void)enqueueUnvisitedObject:(NSObject *)object 32 | { 33 | NSParameterAssert(object != nil); 34 | 35 | [_unvisitedObjects addObject:object]; 36 | } 37 | 38 | - (NSObject *)dequeueUnvisitedObject 39 | { 40 | NSObject *object = [_unvisitedObjects anyObject]; 41 | [_unvisitedObjects removeObject:object]; 42 | 43 | return object; 44 | } 45 | 46 | - (void)addVisitedObject:(NSObject *)object 47 | { 48 | NSParameterAssert(object != nil); 49 | 50 | [_visitedObjects addObject:object]; 51 | } 52 | 53 | - (BOOL)isVisitedObject:(NSObject *)object 54 | { 55 | return object && [_visitedObjects containsObject:object]; 56 | } 57 | 58 | - (void)addSerializedObject:(NSDictionary *)serializedObject 59 | { 60 | NSParameterAssert(serializedObject[@"id"] != nil); 61 | _serializedObjects[serializedObject[@"id"]] = serializedObject; 62 | } 63 | 64 | - (NSArray *)allSerializedObjects 65 | { 66 | return [_serializedObjects allValues]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPPassThroughValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPPassThroughValueTransformer 7 | 8 | + (Class)transformedValueClass 9 | { 10 | return [NSObject class]; 11 | } 12 | 13 | + (BOOL)allowsReverseTransformation 14 | { 15 | return NO; 16 | } 17 | 18 | - (id)transformedValue:(id)value 19 | { 20 | if ([[NSNull null] isEqual:value]) { 21 | return nil; 22 | } 23 | 24 | if (value == nil) { 25 | return [NSNull null]; 26 | } 27 | 28 | return value; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPPropertyDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @class MPObjectSerializerContext; 7 | 8 | @interface MPPropertySelectorParameterDescription : NSObject 9 | 10 | - (id)initWithDictionary:(NSDictionary *)dictionary; 11 | @property (nonatomic, readonly) NSString *name; 12 | @property (nonatomic, readonly) NSString *type; 13 | 14 | @end 15 | 16 | @interface MPPropertySelectorDescription : NSObject 17 | 18 | - (id)initWithDictionary:(NSDictionary *)dictionary; 19 | @property (nonatomic, readonly) NSString *selectorName; 20 | @property (nonatomic, readonly) NSString *returnType; 21 | @property (nonatomic, readonly) NSArray *parameters; // array of MPPropertySelectorParameterDescription 22 | 23 | @end 24 | 25 | @interface MPPropertyDescription : NSObject 26 | 27 | - (id)initWithDictionary:(NSDictionary *)dictionary; 28 | 29 | @property (nonatomic, readonly) NSString *type; 30 | @property (nonatomic, readonly) BOOL readonly; 31 | @property (nonatomic, readonly) BOOL nofollow; 32 | @property (nonatomic, readonly) BOOL useKeyValueCoding; 33 | @property (nonatomic, readonly) BOOL useInstanceVariableAccess; 34 | @property (nonatomic, readonly) NSString *name; 35 | 36 | @property (nonatomic, readonly) MPPropertySelectorDescription *getSelectorDescription; 37 | @property (nonatomic, readonly) MPPropertySelectorDescription *setSelectorDescription; 38 | 39 | - (BOOL)shouldReadPropertyValueForObject:(NSObject *)object; 40 | 41 | - (NSValueTransformer *)valueTransformer; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPSequenceGenerator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @interface MPSequenceGenerator : NSObject 7 | 8 | - (int32_t)nextValue; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPSequenceGenerator.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | #import "MPSequenceGenerator.h" 6 | 7 | @implementation MPSequenceGenerator 8 | 9 | { 10 | int32_t _value; 11 | } 12 | 13 | - (id)init 14 | { 15 | return [self initWithInitialValue:0]; 16 | } 17 | 18 | - (id)initWithInitialValue:(int32_t)initialValue 19 | { 20 | self = [super init]; 21 | if (self) { 22 | _value = initialValue; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | - (int32_t)nextValue 29 | { 30 | return OSAtomicAdd32(1, &_value); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPSurvey.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface MPSurvey : NSObject 4 | 5 | @property (nonatomic, readonly) NSUInteger ID; 6 | @property (nonatomic, readonly, strong) NSString *name; 7 | @property (nonatomic, readonly) NSUInteger collectionID; 8 | @property (nonatomic, readonly, strong) NSArray *questions; 9 | 10 | + (MPSurvey *)surveyWithJSONObject:(NSDictionary *)object; 11 | 12 | - (instancetype)init __unavailable; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPSurvey.m: -------------------------------------------------------------------------------- 1 | #if ! __has_feature(objc_arc) 2 | #error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag on this file. 3 | #endif 4 | 5 | #import "MPLogging.h" 6 | #import "MPSurvey.h" 7 | #import "MPSurveyQuestion.h" 8 | 9 | @interface MPSurvey () 10 | 11 | @property (nonatomic) NSUInteger ID; 12 | @property (nonatomic, strong) NSString *name; 13 | @property (nonatomic) NSUInteger collectionID; 14 | @property (nonatomic, strong) NSArray *questions; 15 | 16 | - (id)initWithID:(NSUInteger)ID name:(NSString *)name collectionID:(NSUInteger)collectionID andQuestions:(NSArray *)questions; 17 | 18 | @end 19 | 20 | @implementation MPSurvey 21 | 22 | + (MPSurvey *)surveyWithJSONObject:(NSDictionary *)object 23 | { 24 | if (object == nil) { 25 | MixpanelError(@"survey json object should not be nil"); 26 | return nil; 27 | } 28 | NSNumber *ID = object[@"id"]; 29 | if (!([ID isKindOfClass:[NSNumber class]] && [ID integerValue] > 0)) { 30 | MixpanelError(@"invalid survey id: %@", ID); 31 | return nil; 32 | } 33 | NSString *name = object[@"name"]; 34 | if (![name isKindOfClass:[NSString class]]) { 35 | MixpanelError(@"invalid survey name: %@", name); 36 | return nil; 37 | } 38 | NSArray *collections = object[@"collections"]; 39 | if (!([collections isKindOfClass:[NSArray class]] && [collections count] > 0)) { 40 | MixpanelError(@"invalid survey collections: %@", collections); 41 | return nil; 42 | } 43 | NSDictionary *collection = collections[0]; 44 | if (![collection isKindOfClass:[NSDictionary class]]) { 45 | MixpanelError(@"invalid survey collection: %@", collection); 46 | return nil; 47 | } 48 | NSNumber *collectionID = collection[@"id"]; 49 | if (!([collectionID isKindOfClass:[NSNumber class]] && [collectionID integerValue] > 0)) { 50 | MixpanelError(@"invalid survey collection id: %@", collectionID); 51 | return nil; 52 | } 53 | NSMutableArray *questions = [NSMutableArray array]; 54 | for (NSDictionary *question in object[@"questions"]) { 55 | MPSurveyQuestion *q = [MPSurveyQuestion questionWithJSONObject:question]; 56 | if (q) { 57 | [questions addObject:q]; 58 | } 59 | } 60 | return [[MPSurvey alloc] initWithID:[ID unsignedIntegerValue] 61 | name:name 62 | collectionID:[collectionID unsignedIntegerValue] 63 | andQuestions:[NSArray arrayWithArray:questions]]; 64 | } 65 | 66 | - (id)initWithID:(NSUInteger)ID name:(NSString *)name collectionID:(NSUInteger)collectionID andQuestions:(NSArray *)questions 67 | { 68 | if (self = [super init]) { 69 | BOOL valid = YES; 70 | if (!(name && name.length > 0)) { 71 | valid = NO; 72 | MixpanelError(@"Invalid survey name %@", name); 73 | } 74 | if (!(questions && [questions count] > 0)) { 75 | valid = NO; 76 | MixpanelError(@"Survey must have at least one question %@", questions); 77 | } 78 | 79 | if (valid) { 80 | _ID = ID; 81 | self.name = name; 82 | _collectionID = collectionID; 83 | self.questions = questions; 84 | } else { 85 | self = nil; 86 | } 87 | } 88 | return self; 89 | } 90 | 91 | - (NSString *)description 92 | { 93 | return [NSString stringWithFormat:@"%@, (ID:%lu, collection:%lu questions:%lu)", self.name, (unsigned long)self.ID, (unsigned long)self.collectionID, (unsigned long)[self.questions count]]; 94 | } 95 | 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPSurveyNavigationController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "Mixpanel.h" 4 | #import "MPSurvey.h" 5 | 6 | @protocol MPSurveyNavigationControllerDelegate; 7 | 8 | @interface MPSurveyNavigationController : UIViewController 9 | 10 | @property (nonatomic, strong) MPSurvey *survey; 11 | @property (nonatomic, strong) UIImage *backgroundImage; 12 | @property (nonatomic, weak) id delegate; 13 | 14 | @end 15 | 16 | @protocol MPSurveyNavigationControllerDelegate 17 | 18 | - (void)surveyController:(MPSurveyNavigationController *)controller wasDismissedWithAnswers:(NSArray *)answers; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPSurveyQuestion.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface MPSurveyQuestion : NSObject 4 | 5 | @property (nonatomic, readonly) NSUInteger ID; 6 | @property (nonatomic, readonly, strong) NSString *type; 7 | @property (nonatomic, readonly, strong) NSString *prompt; 8 | 9 | + (MPSurveyQuestion *)questionWithJSONObject:(NSObject *)object; 10 | 11 | @end 12 | 13 | @interface MPSurveyMultipleChoiceQuestion : MPSurveyQuestion 14 | 15 | @property (nonatomic, readonly, strong) NSArray *choices; 16 | 17 | @end 18 | 19 | @interface MPSurveyTextQuestion : MPSurveyQuestion 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPSurveyQuestionViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "MPSurveyQuestion.h" 4 | 5 | @protocol MPSurveyQuestionViewControllerDelegate; 6 | 7 | @interface MPSurveyQuestionViewController : UIViewController 8 | 9 | @property (nonatomic, weak) id delegate; 10 | @property (nonatomic, strong) MPSurveyQuestion *question; 11 | @property (nonatomic, strong) UIColor *highlightColor; 12 | 13 | @end 14 | 15 | @protocol MPSurveyQuestionViewControllerDelegate 16 | - (void)questionController:(MPSurveyQuestionViewController *)controller didReceiveAnswerProperties:(NSDictionary *)properties; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPSwizzler.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPSwizzler.h 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 1/5/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // Cast to turn things that are not ids into NSMapTable keys 12 | #define MAPTABLE_ID(x) (__bridge id)((void *)x) 13 | 14 | typedef void (^swizzleBlock)(); 15 | 16 | @interface MPSwizzler : NSObject 17 | 18 | + (void)swizzleSelector:(SEL)aSelector onClass:(Class)aClass withBlock:(swizzleBlock)block named:(NSString *)aName; 19 | + (void)unswizzleSelector:(SEL)aSelector onClass:(Class)aClass named:(NSString *)aName; 20 | + (void)printSwizzles; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPTweak.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @protocol MPTweakObserver; 13 | 14 | /** 15 | @abstract Represents a possible value of a tweak. 16 | @discussion Should be able to be persisted in user defaults. 17 | For minimum and maximum values, should implement -compare:. 18 | */ 19 | typedef id MPTweakValue; 20 | 21 | /** 22 | @abstract Represents a tweak 23 | @discussion A tweak contains a persistent, editable value. 24 | */ 25 | @interface MPTweak : NSObject 26 | 27 | /** 28 | @abstract Creates a new tweak model. 29 | @discussion This is the designated initializer. 30 | */ 31 | - (instancetype)initWithName:(NSString *)name andEncoding:(NSString *)encoding; 32 | 33 | /** 34 | @abstract This tweak's unique name. 35 | @discussion Used when reading and writing the tweak's value. 36 | */ 37 | @property (nonatomic, copy, readonly) NSString *name; 38 | 39 | /** 40 | @abstract This tweak's value encoding, as returned by @encoding 41 | */ 42 | @property (nonatomic, copy, readonly) NSString *encoding; 43 | 44 | /** 45 | @abstract The default value of the tweak. 46 | @discussion Use this when the current value is unset. 47 | */ 48 | @property (nonatomic, strong, readwrite) MPTweakValue defaultValue; 49 | 50 | /** 51 | @abstract The current value of the tweak. Can be nil. 52 | @discussion Changes to this property will be propagated to disk. 53 | */ 54 | @property (nonatomic, strong, readwrite) MPTweakValue currentValue; 55 | 56 | /** 57 | @abstract The minimum value of the tweak. 58 | @discussion Optional. If nil, there is no minimum. 59 | */ 60 | @property (nonatomic, strong, readwrite) MPTweakValue minimumValue; 61 | 62 | /** 63 | @abstract The maximum value of the tweak. 64 | @discussion Optional. If nil, there is no maximum. 65 | */ 66 | @property (nonatomic, strong, readwrite) MPTweakValue maximumValue; 67 | 68 | /** 69 | @abstract Adds an observer to the tweak. 70 | @param object The observer. Must not be nil. 71 | @discussion A weak reference is taken on the observer. 72 | */ 73 | - (void)addObserver:(id)observer; 74 | 75 | /** 76 | @abstract Removes an observer from the tweak. 77 | @param observer The observer to remove. Must not be nil. 78 | @discussion Optional, removing an observer isn't required. 79 | */ 80 | - (void)removeObserver:(id)observer; 81 | 82 | @end 83 | 84 | /** 85 | @abstract Responds to updates when a tweak changes. 86 | */ 87 | @protocol MPTweakObserver 88 | 89 | /** 90 | @abstract Called when a tweak's value changes. 91 | @param tweak The tweak which changed in value. 92 | */ 93 | - (void)tweakDidChange:(MPTweak *)tweak; 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPTweak.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "MPTweak.h" 11 | 12 | @implementation MPTweak { 13 | NSHashTable *_observers; 14 | } 15 | 16 | - (instancetype)initWithName:(NSString *)name andEncoding:(NSString *)encoding 17 | { 18 | if ((self = [super init])) { 19 | _name = name; 20 | _encoding = encoding; 21 | _currentValue = nil; 22 | _defaultValue = nil; 23 | _minimumValue = nil; 24 | _maximumValue = nil; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)setCurrentValue:(MPTweakValue)currentValue 30 | { 31 | if (_minimumValue != nil && currentValue != nil && [_minimumValue compare:currentValue] == NSOrderedDescending) { 32 | currentValue = _minimumValue; 33 | } 34 | 35 | if (_maximumValue != nil && currentValue != nil && [_maximumValue compare:currentValue] == NSOrderedAscending) { 36 | currentValue = _maximumValue; 37 | } 38 | 39 | if (_currentValue != currentValue) { 40 | _currentValue = currentValue; 41 | for (id observer in [_observers setRepresentation]) { 42 | [observer tweakDidChange:self]; 43 | } 44 | } 45 | } 46 | 47 | - (void)addObserver:(id)observer 48 | { 49 | if (_observers == nil) { 50 | _observers = [NSHashTable weakObjectsHashTable]; 51 | } 52 | 53 | NSAssert(observer != nil, @"observer is required"); 54 | [_observers addObject:observer]; 55 | } 56 | 57 | - (void)removeObserver:(id)observer 58 | { 59 | NSAssert(observer != nil, @"observer is required"); 60 | [_observers removeObject:observer]; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPTweakInline.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "MPTweakInlineInternal.h" 11 | 12 | /*! 13 | @abstract Loads the value of a tweak inline. 14 | @discussion To use a tweak, use this instead of the constant value you otherwise would. 15 | To use the same tweak in two places, define a C function that returns MPTweakValue. 16 | @param name_ The name of the tweak. Must be a constant NSString. 17 | @param default_ The default value of the tweak. If the user doesn't configure 18 | a custom value or the build is a release build, then the default value is used. 19 | The default value supports a variety of types, but all must be constant literals. 20 | Supported types include: BOOL, NSInteger, NSUInteger, CGFloat, NSString *, char *. 21 | @param min_ Optional, for numbers. The minimum value. Same restrictions as default. 22 | @param max_ Optional, for numbers. The maximum value. Same restrictions as default. 23 | @return The current value of the tweak, or the default value if none is set. 24 | */ 25 | #define MPTweakValue(name_, ...) _MPTweakValue(name_, __VA_ARGS__) 26 | 27 | /*! 28 | @abstract Binds an object property to a tweak. 29 | @param object_ The object to bind to. 30 | @param property_ The property to bind. 31 | @param name_ The name of the tweak. Must be a constant NSString. 32 | @param default_ The default value of the tweak. If the user doesn't configure 33 | a custom value or the build is a release build, then the default value is used. 34 | The default value supports a variety of types, but all must be constant literals. 35 | Supported types include: BOOL, NSInteger, NSUInteger, CGFloat, NSString *, char *. 36 | @param min_ Optional, for numbers. The minimum value. Same restrictions as default. 37 | @param max_ Optional, for numbers. The maximum value. Same restrictions as default. 38 | @discussion As long as the object is alive, the property will be updated to match the tweak. 39 | */ 40 | #define MPTweakBind(object_, property_, name_, ...) _MPTweakBind(object_, property_, name_, __VA_ARGS__) 41 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPTweakStore.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import "MPTweak.h" 12 | 13 | @class MPTweak; 14 | 15 | /** 16 | @abstract The global store for tweaks. 17 | */ 18 | @interface MPTweakStore : NSObject 19 | 20 | /** 21 | @abstract Creates or returns the shared global store. 22 | */ 23 | + (instancetype)sharedInstance; 24 | 25 | /** 26 | @abstract The tweak categories in the store. 27 | */ 28 | @property (nonatomic, copy, readonly) NSArray *tweaks; 29 | 30 | /** 31 | @abstract Finds a tweak by name. 32 | @param name The name of the tweak to find. 33 | @return The tweak if found, nil otherwise. 34 | */ 35 | - (MPTweak *)tweakWithName:(NSString *)name; 36 | 37 | /** 38 | @abstract Registers a tweak with the store. 39 | @param tweak The tweak to register. 40 | */ 41 | - (void)addTweak:(MPTweak *)tweak; 42 | 43 | /** 44 | @abstract Removes a tweak from the store. 45 | @param tweak The tweak to remove. 46 | */ 47 | - (void)removeTweak:(MPTweak *)tweak; 48 | 49 | /** 50 | @abstract Resets all tweaks in the store. 51 | */ 52 | - (void)reset; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPTweakStore.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "MPTweak.h" 11 | #import "MPTweakStore.h" 12 | 13 | @implementation MPTweakStore { 14 | NSMutableArray *_orderedTweaks; 15 | NSMutableDictionary *_namedTweaks; 16 | } 17 | 18 | + (instancetype)sharedInstance 19 | { 20 | static MPTweakStore *sharedInstance = nil; 21 | 22 | static dispatch_once_t onceToken; 23 | dispatch_once(&onceToken, ^{ 24 | sharedInstance = [[self alloc] init]; 25 | }); 26 | 27 | return sharedInstance; 28 | } 29 | 30 | - (instancetype)init 31 | { 32 | if ((self = [super init])) { 33 | _orderedTweaks = [[NSMutableArray alloc] initWithCapacity:16]; 34 | _namedTweaks = [[NSMutableDictionary alloc] initWithCapacity:16]; 35 | } 36 | 37 | return self; 38 | } 39 | 40 | - (NSArray *)tweaks 41 | { 42 | return [_orderedTweaks copy]; 43 | } 44 | 45 | - (MPTweak *)tweakWithName:(NSString *)name 46 | { 47 | return _namedTweaks[name]; 48 | } 49 | 50 | - (void)addTweak:(MPTweak *)tweak 51 | { 52 | [_namedTweaks setObject:tweak forKey:tweak.name]; 53 | [_orderedTweaks addObject:tweak]; 54 | } 55 | 56 | - (void)removeTweak:(MPTweak *)tweak 57 | { 58 | [_namedTweaks removeObjectForKey:tweak.name]; 59 | [_orderedTweaks removeObject:tweak]; 60 | } 61 | 62 | - (void)reset 63 | { 64 | for (MPTweak *tweak in self.tweaks) { 65 | tweak.currentValue = nil; 66 | } 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPTypeDescription.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @interface MPTypeDescription : NSObject 7 | 8 | - (id)initWithDictionary:(NSDictionary *)dictionary; 9 | 10 | @property (nonatomic, readonly) NSString *name; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPTypeDescription.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPTypeDescription.h" 5 | 6 | @implementation MPTypeDescription 7 | 8 | - (id)initWithDictionary:(NSDictionary *)dictionary 9 | { 10 | self = [super init]; 11 | if (self) { 12 | _name = [dictionary[@"name"] copy]; 13 | } 14 | 15 | return self; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPUIColorToNSStringValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPUIColorToNSStringValueTransformer 7 | 8 | + (Class)transformedValueClass 9 | { 10 | return [NSString class]; 11 | } 12 | 13 | + (BOOL)allowsReverseTransformation 14 | { 15 | return YES; 16 | } 17 | 18 | - (id)transformedValue:(id)value 19 | { 20 | if (value && [value isKindOfClass:[UIColor class]]) { 21 | UIColor *colorValue = (UIColor *)value; 22 | 23 | CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(CGColorGetColorSpace(colorValue.CGColor)); 24 | if (colorSpaceModel == kCGColorSpaceModelMonochrome || colorSpaceModel == kCGColorSpaceModelRGB) { 25 | size_t numberOfComponents = CGColorGetNumberOfComponents(colorValue.CGColor); 26 | const CGFloat *components = CGColorGetComponents(colorValue.CGColor); 27 | 28 | if (colorSpaceModel == kCGColorSpaceModelMonochrome && numberOfComponents >= 1) { 29 | CGFloat w = (255 * components[0]); 30 | CGFloat a = (numberOfComponents > 1 ? components[1] : 1.0f); 31 | 32 | return [NSString stringWithFormat:@"rgba(%.0f, %.0f, %.0f, %.2f)", w, w, w, a]; 33 | } 34 | else if (colorSpaceModel == kCGColorSpaceModelRGB && numberOfComponents >= 3) 35 | { 36 | CGFloat r = (255 * components[0]); 37 | CGFloat g = (255 * components[1]); 38 | CGFloat b = (255 * components[2]); 39 | CGFloat a = (numberOfComponents > 3 ? components[3] : 1.0f); 40 | 41 | return [NSString stringWithFormat:@"rgba(%.0f, %.0f, %.0f, %.2f)", r, g, b, a]; 42 | } 43 | } 44 | } 45 | 46 | return nil; 47 | } 48 | 49 | - (id)reverseTransformedValue:(id)value 50 | { 51 | if ([value isKindOfClass:[NSString class]]) { 52 | NSString *stringValue = (NSString *)value; 53 | 54 | NSScanner *scanner = [NSScanner scannerWithString:stringValue]; 55 | [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"rgba(), "]]; 56 | [scanner setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]]; 57 | 58 | int r = 0, g = 0, b = 0; 59 | float a = 1.0f; 60 | if ([scanner scanInt:&r] && 61 | [scanner scanInt:&g] && 62 | [scanner scanInt:&b] && 63 | [scanner scanFloat:&a]) 64 | { 65 | UIColor *color = [[UIColor alloc] initWithRed:(r/255.0f) green:(g/255.0f) blue:(b/255.0f) alpha:a]; 66 | return color; 67 | } 68 | } 69 | 70 | return nil; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPUIControlBinding.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPUIControlBinding.h 3 | // HelloMixpanel 4 | // 5 | // Created by Amanda Canyon on 8/4/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPEventBinding.h" 10 | 11 | @interface MPUIControlBinding : MPEventBinding 12 | 13 | @property (nonatomic, readonly) UIControlEvents controlEvent; 14 | @property (nonatomic, readonly) UIControlEvents verifyEvent; 15 | 16 | - (instancetype)init __unavailable; 17 | - (id)initWithEventName:(NSString *)eventName 18 | onPath:(NSString *)path 19 | withControlEvent:(UIControlEvents)controlEvent 20 | andVerifyEvent:(UIControlEvents)verifyEvent; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPUIEdgeInsetsToNSDictionaryValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPUIEdgeInsetsToNSDictionaryValueTransformer 7 | 8 | + (Class)transformedValueClass 9 | { 10 | return [NSDictionary class]; 11 | } 12 | 13 | + (BOOL)allowsReverseTransformation 14 | { 15 | return YES; 16 | } 17 | 18 | - (id)transformedValue:(id)value 19 | { 20 | if ([value respondsToSelector:@selector(UIEdgeInsetsValue)]) { 21 | UIEdgeInsets edgeInsetsValue = [value UIEdgeInsetsValue]; 22 | 23 | return @{ 24 | @"top" : @(edgeInsetsValue.top), 25 | @"bottom" : @(edgeInsetsValue.bottom), 26 | @"left" : @(edgeInsetsValue.left), 27 | @"right" : @(edgeInsetsValue.right) 28 | }; 29 | } 30 | 31 | return nil; 32 | } 33 | 34 | - (id)reverseTransformedValue:(id)value 35 | { 36 | if ([value isKindOfClass:[NSDictionary class]]) { 37 | NSDictionary *dictionaryValue = value; 38 | 39 | id top = dictionaryValue[@"top"]; 40 | id bottom = dictionaryValue[@"bottom"]; 41 | id left = dictionaryValue[@"left"]; 42 | id right = dictionaryValue[@"right"]; 43 | 44 | if (top && bottom && left && right) { 45 | UIEdgeInsets edgeInsets = UIEdgeInsetsMake([top floatValue], [left floatValue], [bottom floatValue], [right floatValue]); 46 | return [NSValue valueWithUIEdgeInsets:edgeInsets]; 47 | } 48 | } 49 | 50 | return [NSValue valueWithUIEdgeInsets:UIEdgeInsetsZero]; 51 | } 52 | 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPUIFontToNSDictionaryValueTransformer.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import "MPValueTransformers.h" 5 | 6 | @implementation MPUIFontToNSDictionaryValueTransformer 7 | 8 | { 9 | 10 | } 11 | + (Class)transformedValueClass 12 | { 13 | return [NSDictionary class]; 14 | } 15 | 16 | + (BOOL)allowsReverseTransformation 17 | { 18 | return YES; 19 | } 20 | 21 | - (id)transformedValue:(id)value 22 | { 23 | if ([value isKindOfClass:[UIFont class]]) { 24 | UIFont *fontValue = value; 25 | 26 | return @{ 27 | @"familyName": fontValue.familyName, 28 | @"fontName": fontValue.fontName, 29 | @"pointSize": @(fontValue.pointSize), 30 | }; 31 | } 32 | 33 | return nil; 34 | } 35 | 36 | - (id)reverseTransformedValue:(id)value 37 | { 38 | if ([value isKindOfClass:[NSDictionary class]]) { 39 | NSDictionary *dictionaryValue = value; 40 | 41 | NSNumber *pointSize = dictionaryValue[@"pointSize"]; 42 | NSString *fontName = dictionaryValue[@"fontName"]; 43 | 44 | float fontSize = [pointSize floatValue]; 45 | if (fontSize > 0.0f && fontName) { 46 | UIFont *systemFont = [UIFont systemFontOfSize:fontSize]; 47 | UIFont *boldSystemFont = [UIFont boldSystemFontOfSize:fontSize]; 48 | UIFont *italicSystemFont = [UIFont italicSystemFontOfSize:fontSize]; 49 | 50 | if ([systemFont.fontName isEqualToString:fontName]) { 51 | return systemFont; 52 | } 53 | else if ([boldSystemFont.fontName isEqualToString:fontName]) 54 | { 55 | return boldSystemFont; 56 | } 57 | else if ([italicSystemFont.fontName isEqualToString:fontName]) 58 | { 59 | return italicSystemFont; 60 | } else { 61 | return [UIFont fontWithName:fontName size:fontSize]; 62 | } 63 | } 64 | } 65 | 66 | return nil; 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPUITableViewBinding.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPUITableViewBinding.h 3 | // HelloMixpanel 4 | // 5 | // Created by Amanda Canyon on 8/5/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import "MPEventBinding.h" 10 | 11 | @interface MPUITableViewBinding : MPEventBinding 12 | 13 | - (instancetype)init __unavailable; 14 | - (instancetype)initWithEventName:(NSString *)eventName onPath:(NSString *)path withDelegate:(Class)delegateClass; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPValueTransformers.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | @interface MPPassThroughValueTransformer : NSValueTransformer 5 | 6 | @end 7 | 8 | @interface MPBOOLToNSNumberValueTransformer : NSValueTransformer 9 | 10 | @end 11 | 12 | @interface MPCATransform3DToNSDictionaryValueTransformer : NSValueTransformer 13 | 14 | @end 15 | 16 | @interface MPCGAffineTransformToNSDictionaryValueTransformer : NSValueTransformer 17 | 18 | @end 19 | 20 | @interface MPCGColorRefToNSStringValueTransformer : NSValueTransformer 21 | 22 | @end 23 | 24 | @interface MPCGPointToNSDictionaryValueTransformer : NSValueTransformer 25 | 26 | @end 27 | 28 | @interface MPCGRectToNSDictionaryValueTransformer : NSValueTransformer 29 | 30 | @end 31 | 32 | @interface MPCGSizeToNSDictionaryValueTransformer : NSValueTransformer 33 | 34 | @end 35 | 36 | @interface MPNSAttributedStringToNSDictionaryValueTransformer : NSValueTransformer 37 | 38 | @end 39 | 40 | @interface MPUIColorToNSStringValueTransformer : NSValueTransformer 41 | 42 | @end 43 | 44 | @interface MPUIEdgeInsetsToNSDictionaryValueTransformer : NSValueTransformer 45 | 46 | @end 47 | 48 | @interface MPUIFontToNSDictionaryValueTransformer : NSValueTransformer 49 | 50 | @end 51 | 52 | @interface MPUIImageToNSDictionaryValueTransformer : NSValueTransformer 53 | 54 | @end 55 | 56 | @interface MPNSNumberToCGFloatValueTransformer : NSValueTransformer 57 | 58 | @end 59 | 60 | __unused static id transformValue(id value, NSString *toType) 61 | { 62 | assert(value != nil); 63 | 64 | if ([value isKindOfClass:[NSClassFromString(toType) class]]) { 65 | return [[NSValueTransformer valueTransformerForName:@"MPPassThroughValueTransformer"] transformedValue:value]; 66 | } 67 | 68 | NSString *fromType = nil; 69 | NSArray *validTypes = @[[NSString class], [NSNumber class], [NSDictionary class], [NSArray class], [NSNull class]]; 70 | for (Class c in validTypes) { 71 | if ([value isKindOfClass:c]) { 72 | fromType = NSStringFromClass(c); 73 | break; 74 | } 75 | } 76 | 77 | assert(fromType != nil); 78 | NSValueTransformer *transformer = nil; 79 | NSString *forwardTransformerName = [NSString stringWithFormat:@"MP%@To%@ValueTransformer", fromType, toType]; 80 | transformer = [NSValueTransformer valueTransformerForName:forwardTransformerName]; 81 | if (transformer) { 82 | return [transformer transformedValue:value]; 83 | } 84 | 85 | NSString *reverseTransformerName = [NSString stringWithFormat:@"MP%@To%@ValueTransformer", toType, fromType]; 86 | transformer = [NSValueTransformer valueTransformerForName:reverseTransformerName]; 87 | if (transformer && [[transformer class] allowsReverseTransformation]) { 88 | return [transformer reverseTransformedValue:value]; 89 | } 90 | 91 | return [[NSValueTransformer valueTransformerForName:@"MPPassThroughValueTransformer"] transformedValue:value]; 92 | } 93 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPVariant.h: -------------------------------------------------------------------------------- 1 | // 2 | // MPVariant.h 3 | // HelloMixpanel 4 | // 5 | // Created by Alex Hofsteede on 28/4/14. 6 | // Copyright (c) 2014 Mixpanel. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MPVariant : NSObject 12 | 13 | @property (nonatomic) NSUInteger ID; 14 | @property (nonatomic) NSUInteger experimentID; 15 | 16 | /*! 17 | @property 18 | 19 | @abstract 20 | Whether this specific variant is currently running on the device. 21 | 22 | @discussion 23 | This property will not be restored on unarchive, as the variant will need 24 | to be run again once the app is restarted. 25 | */ 26 | @property (nonatomic, readonly) BOOL running; 27 | 28 | /*! 29 | @property 30 | 31 | @abstract 32 | Whether the variant should not run anymore. 33 | 34 | @discussion 35 | Variants are marked as finished when we no longer see them in a decide response. 36 | They will continue running (ie their changes will be visible) until the next 37 | time the app starts. 38 | */ 39 | @property (nonatomic, readonly) BOOL finished; 40 | 41 | + (MPVariant *)variantWithJSONObject:(NSDictionary *)object; 42 | 43 | - (void)addActionsFromJSONObject:(NSArray *)actions andExecute:(BOOL)exec; 44 | - (void)addActionFromJSONObject:(NSDictionary *)object andExecute:(BOOL)exec; 45 | - (void)addTweaksFromJSONObject:(NSArray *)tweaks andExecute:(BOOL)exec; 46 | - (void)addTweakFromJSONObject:(NSDictionary *)object andExecute:(BOOL)exec; 47 | - (void)removeActionWithName:(NSString *)name; 48 | 49 | /*! 50 | @method 51 | 52 | @abstract 53 | Executes the variant, including all of its actions and tweaks. 54 | 55 | @discussion 56 | This immediately applies the changes associated with this variant. 57 | */ 58 | - (void)execute; 59 | 60 | /*! 61 | @method 62 | 63 | @abstract 64 | Stops the variant, including all of its actions and tweaks. 65 | 66 | @discussion 67 | This immediately applies the reverse of this variant. including 68 | reversing all actions and tweaks to their original values. 69 | */ 70 | - (void)stop; 71 | 72 | /*! 73 | @method 74 | 75 | @abstract 76 | Sets the finished flag on this variant, does not take any actions. 77 | 78 | @discussion 79 | The finished flag marks this variant as one that should not be run 80 | anymore the next time the app opens, but we leave it running so that 81 | the UI doesn't change during the user session. 82 | */ 83 | - (void)finish; 84 | 85 | /*! 86 | @method 87 | 88 | @abstract 89 | Unsets the finished flag on this variant, does not take any actions. 90 | 91 | @discussion 92 | If the finished flag is unset, the variant will continue to run the 93 | next time the app starts. 94 | */ 95 | - (void)restart; 96 | 97 | @end 98 | 99 | @interface MPVariantAction : NSObject 100 | 101 | @end 102 | 103 | @interface MPVariantTweak : NSObject 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/MPWebSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | // 4 | 5 | // Portions Copyright 2012 Square Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | #import 22 | 23 | typedef enum { 24 | MPWebSocketStateConnecting = 0, 25 | MPWebSocketStateOpen = 1, 26 | MPWebSocketStateClosing = 2, 27 | MPWebSocketStateClosed = 3, 28 | } MPWebSocketReadyState; 29 | 30 | @class MPWebSocket; 31 | 32 | extern NSString *const MPWebSocketErrorDomain; 33 | 34 | #pragma mark - MPWebSocketDelegate 35 | 36 | @protocol MPWebSocketDelegate; 37 | 38 | #pragma mark - MPWebSocket 39 | 40 | @interface MPWebSocket : NSObject 41 | 42 | @property (nonatomic, assign) id delegate; 43 | 44 | @property (nonatomic, readonly) MPWebSocketReadyState readyState; 45 | @property (nonatomic, readonly, retain) NSURL *url; 46 | 47 | // This returns the negotiated protocol. 48 | // It will be nil until after the handshake completes. 49 | @property (nonatomic, readonly, copy) NSString *protocol; 50 | 51 | // Protocols should be an array of strings that turn into Sec-WebSocket-Protocol. 52 | - (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; 53 | - (id)initWithURLRequest:(NSURLRequest *)request; 54 | 55 | // Some helper constructors. 56 | - (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; 57 | - (id)initWithURL:(NSURL *)url; 58 | 59 | // Delegate queue will be dispatch_main_queue by default. 60 | // You cannot set both OperationQueue and dispatch_queue. 61 | - (void)setDelegateOperationQueue:(NSOperationQueue*) queue; 62 | - (void)setDelegateDispatchQueue:(dispatch_queue_t) queue; 63 | 64 | // By default, it will schedule itself on +[NSRunLoop mp_networkRunLoop] using defaultModes. 65 | - (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; 66 | - (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; 67 | 68 | // MPWebSockets are intended for one-time-use only. Open should be called once and only once. 69 | - (void)open; 70 | 71 | - (void)close; 72 | - (void)closeWithCode:(NSInteger)code reason:(NSString *)reason; 73 | 74 | // Send a UTF8 String or Data. 75 | - (void)send:(id)data; 76 | 77 | @end 78 | 79 | #pragma mark - MPWebSocketDelegate 80 | 81 | @protocol MPWebSocketDelegate 82 | 83 | // message will either be an NSString if the server is using text 84 | // or NSData if the server is using binary. 85 | - (void)webSocket:(MPWebSocket *)webSocket didReceiveMessage:(id)message; 86 | 87 | @optional 88 | 89 | - (void)webSocketDidOpen:(MPWebSocket *)webSocket; 90 | - (void)webSocket:(MPWebSocket *)webSocket didFailWithError:(NSError *)error; 91 | - (void)webSocket:(MPWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean; 92 | 93 | @end 94 | 95 | #pragma mark - NSURLRequest (CertificateAdditions) 96 | 97 | @interface NSURLRequest (CertificateAdditions) 98 | 99 | @property (nonatomic, retain, readonly) NSArray *mp_SSLPinnedCertificates; 100 | 101 | @end 102 | 103 | #pragma mark - NSMutableURLRequest (CertificateAdditions) 104 | 105 | @interface NSMutableURLRequest (CertificateAdditions) 106 | 107 | @property (nonatomic, retain) NSArray *mp_SSLPinnedCertificates; 108 | 109 | @end 110 | 111 | #pragma mark - NSRunLoop (SRWebSocket) 112 | 113 | @interface NSRunLoop (MPWebSocket) 114 | 115 | + (NSRunLoop *)mp_networkRunLoop; 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPArrowLeft.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "MPArrowLeft.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "MPArrowLeft@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPArrowLeft.imageset/MPArrowLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPArrowLeft.imageset/MPArrowLeft.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPArrowLeft.imageset/MPArrowLeft@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPArrowLeft.imageset/MPArrowLeft@2x.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPArrowRight.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "MPArrowRight.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "MPArrowRight@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPArrowRight.imageset/MPArrowRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPArrowRight.imageset/MPArrowRight.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPArrowRight.imageset/MPArrowRight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPArrowRight.imageset/MPArrowRight@2x.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPCheckmark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "MPCheckmark.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "MPCheckmark@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPCheckmark.imageset/MPCheckmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPCheckmark.imageset/MPCheckmark.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPCheckmark.imageset/MPCheckmark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPCheckmark.imageset/MPCheckmark@2x.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPCloseBtn.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "MPCloseBtn.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "MPCloseBtn@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPCloseBtn.imageset/MPCloseBtn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPCloseBtn.imageset/MPCloseBtn.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPCloseBtn.imageset/MPCloseBtn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPCloseBtn.imageset/MPCloseBtn@2x.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPDismissKeyboard.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "MPDismissKeyboard.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "MPDismissKeyboard@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPDismissKeyboard.imageset/MPDismissKeyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPDismissKeyboard.imageset/MPDismissKeyboard.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPDismissKeyboard.imageset/MPDismissKeyboard@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPDismissKeyboard.imageset/MPDismissKeyboard@2x.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPLogo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "MPLogo.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "MPLogo@2x.png" 12 | } 13 | ], 14 | "info" : { 15 | "version" : 1, 16 | "author" : "xcode" 17 | } 18 | } -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPLogo.imageset/MPLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPLogo.imageset/MPLogo.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/Media.xcassets/MPLogo.imageset/MPLogo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/Media.xcassets/MPLogo.imageset/MPLogo@2x.png -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/NSData+MPBase64.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Base64.h 3 | // base64 4 | // 5 | // Created by Matt Gallagher on 2009/06/03. 6 | // Copyright 2009 Matt Gallagher. All rights reserved. 7 | // 8 | // Permission is given to use this source code file, free of charge, in any 9 | // project, commercial or otherwise, entirely at your risk, with the condition 10 | // that any redistribution (in part or whole) of source code must retain 11 | // this copyright and permission notice. Attribution in compiled projects is 12 | // appreciated but not required. 13 | // 14 | 15 | #import 16 | 17 | void *MP_NewBase64Decode( 18 | const char *inputBuffer, 19 | size_t length, 20 | size_t *outputLength); 21 | 22 | char *MP_NewBase64Encode( 23 | const void *inputBuffer, 24 | size_t length, 25 | bool separateLines, 26 | size_t *outputLength); 27 | 28 | @interface NSData (MP_Base64) 29 | 30 | + (NSData *)mp_dataFromBase64String:(NSString *)aString; 31 | - (NSString *)mp_base64EncodedString; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/NSInvocation+MPHelpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Mixpanel. All rights reserved. 3 | 4 | #import 5 | 6 | @interface NSInvocation (MPHelpers) 7 | 8 | - (void)mp_setArgumentsFromArray:(NSArray *)argumentArray; 9 | - (id)mp_returnValue; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/UIColor+MPColor.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface UIColor (MPColor) 4 | 5 | + (UIColor *)mp_applicationPrimaryColor; 6 | + (UIColor *)mp_lightEffectColor; 7 | + (UIColor *)mp_extraLightEffectColor; 8 | + (UIColor *)mp_darkEffectColor; 9 | 10 | - (UIColor *)colorWithSaturationComponent:(CGFloat) saturation; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/UIColor+MPColor.m: -------------------------------------------------------------------------------- 1 | #if ! __has_feature(objc_arc) 2 | #error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag on this file. 3 | #endif 4 | 5 | #import "UIColor+MPColor.h" 6 | 7 | @implementation UIColor (MPColor) 8 | 9 | + (UIColor *)mp_applicationPrimaryColor 10 | { 11 | 12 | UIColor *color; 13 | 14 | // First try and find the color of the UINavigationBar of the top UINavigationController that is showing now. 15 | UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; 16 | UINavigationController *topNavigationController = nil; 17 | 18 | do { 19 | if ([rootViewController isKindOfClass:[UINavigationController class]]) { 20 | topNavigationController = (UINavigationController *)rootViewController; 21 | } else if (rootViewController.navigationController) { 22 | topNavigationController = rootViewController.navigationController; 23 | } 24 | } while ((rootViewController = rootViewController.presentedViewController)); 25 | 26 | if (topNavigationController) { 27 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 28 | if ([[topNavigationController navigationBar] respondsToSelector:@selector(barTintColor)]) { 29 | color = [[topNavigationController navigationBar] barTintColor]; 30 | } else { 31 | color = [topNavigationController navigationBar].tintColor; 32 | } 33 | #else 34 | color = [topNavigationController navigationBar].tintColor; 35 | #endif 36 | } 37 | 38 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 39 | // Then try and use the UINavigationBar default color for the app 40 | if (!color && [[UINavigationBar appearance] respondsToSelector:@selector(barTintColor)]) { 41 | color = [[UINavigationBar appearance] barTintColor]; 42 | } 43 | 44 | // Or the UITabBar default color 45 | if (!color && [[UITabBar appearance] respondsToSelector:@selector(barTintColor)]) { 46 | color = [[UITabBar appearance] barTintColor]; 47 | } 48 | #endif 49 | 50 | return color; 51 | } 52 | 53 | + (UIColor *)mp_lightEffectColor 54 | { 55 | return [UIColor colorWithWhite:1.0f alpha:0.3f]; 56 | } 57 | 58 | + (UIColor *)mp_extraLightEffectColor 59 | { 60 | return [UIColor colorWithWhite:0.97f alpha:0.82f]; 61 | } 62 | 63 | + (UIColor *)mp_darkEffectColor 64 | { 65 | return [UIColor colorWithWhite:0.11f alpha:0.73f]; 66 | } 67 | 68 | - (UIColor *)colorWithSaturationComponent:(CGFloat) saturation 69 | { 70 | UIColor *newColor; 71 | CGFloat h, s, b, a; 72 | if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) { 73 | newColor = [UIColor colorWithHue:h saturation:saturation brightness:b alpha:a]; 74 | } 75 | return newColor; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/UIImage+MPAverageColor.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface UIImage (MPAverageColor) 4 | 5 | - (UIColor *)mp_averageColor; 6 | - (UIColor *)mp_importantColor; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/UIImage+MPAverageColor.m: -------------------------------------------------------------------------------- 1 | #if ! __has_feature(objc_arc) 2 | #error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag on this file. 3 | #endif 4 | 5 | #import "UIImage+MPAverageColor.h" 6 | 7 | @implementation UIImage (MPAverageColor) 8 | 9 | - (UIColor *)mp_averageColor 10 | { 11 | CGSize size = {1, 1}; 12 | UIGraphicsBeginImageContext(size); 13 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 14 | CGContextSetInterpolationQuality(ctx, kCGInterpolationMedium); 15 | [self drawInRect:(CGRect){.size = size} blendMode:kCGBlendModeCopy alpha:1]; 16 | uint8_t *data = CGBitmapContextGetData(ctx); 17 | UIColor *color = [UIColor colorWithRed:data[2] / 255.0f 18 | green:data[1] / 255.0f 19 | blue:data[0] / 255.0f 20 | alpha:1]; 21 | UIGraphicsEndImageContext(); 22 | return color; 23 | } 24 | 25 | - (UIColor *)mp_importantColor 26 | { 27 | UIGraphicsBeginImageContext(self.size); 28 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 29 | 30 | [self drawInRect:(CGRect){.size = self.size} blendMode:kCGBlendModeCopy alpha:1]; 31 | uint8_t *data = CGBitmapContextGetData(ctx); 32 | 33 | NSUInteger indexes = 262144; 34 | char colorIndices[262144] = {0}; 35 | 36 | // only attempt to quantize the header 37 | NSUInteger l = (NSUInteger) ceil(self.size.width * 124.0f); 38 | for (NSUInteger i = 40 * 640; i < l; i++) { 39 | uint8_t red = data[i * 4 + 2]; 40 | uint8_t green = data[i * 4 + 1]; 41 | uint8_t blue = data[i * 4 + 0]; 42 | NSInteger hexColor = (red >> 2) + ((green >> 2) << 6) + ((blue >> 2) << 12); 43 | 44 | if (hexColor > 0 && hexColor < 2621443 && red + green + blue < 255 + 255 + 200 && red != blue && blue != green && green != red) { 45 | colorIndices[hexColor]++; 46 | } 47 | } 48 | 49 | NSUInteger index = 0; 50 | char max = 0; 51 | for (NSUInteger i = 0; i < indexes; i++) { 52 | if (colorIndices[i] > max) { 53 | max = colorIndices[i]; 54 | index = i; 55 | } 56 | } 57 | 58 | UIColor *color = [UIColor colorWithRed:(((index & 63) << 2) + 3) / 255.0f 59 | green:(((index >> 4) & 252) + 3) / 255.0f 60 | blue:(((index >> 10) & 252) + 3) / 255.0f 61 | alpha:1]; 62 | UIGraphicsEndImageContext(); 63 | return color; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/_MPTweakBindObserver.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @class MPTweak; 13 | 14 | /** 15 | @abstract Block to call when an update is observed. 16 | @param object The object that the observer is attached to. 17 | */ 18 | typedef void (^_MPTweakBindObserverBlock)(id object); 19 | 20 | /** 21 | @abstract Observes a tweak to issue bind updates. 22 | @discussion This is an implementation detail of {@ref MPTweakBind}. 23 | */ 24 | @interface _MPTweakBindObserver : NSObject 25 | 26 | /** 27 | @abstract Designated initializer. 28 | @param tweak The tweak to observe. 29 | @param block The block to call on change. 30 | @return A new bind observer. 31 | */ 32 | - (instancetype)initWithTweak:(MPTweak *)tweak block:(_MPTweakBindObserverBlock)block; 33 | 34 | /** 35 | @abstract Attaches to an object and deallocates with it. 36 | @discussion Useful to create a limited lifetime for the observer. 37 | */ 38 | - (void)attachToObject:(id)object; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/_MPTweakBindObserver.m: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014-present, Facebook, Inc. 3 | All rights reserved. 4 | 5 | This source code is licensed under the BSD-style license found in the 6 | LICENSE file in the root directory of this source tree. An additional grant 7 | of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import "_MPTweakBindObserver.h" 12 | #import "MPTweak.h" 13 | 14 | @interface _MPTweakBindObserver () 15 | 16 | @end 17 | 18 | @implementation _MPTweakBindObserver { 19 | MPTweak *_tweak; 20 | _MPTweakBindObserverBlock _block; 21 | __weak id _object; 22 | } 23 | 24 | - (instancetype)initWithTweak:(MPTweak *)tweak block:(_MPTweakBindObserverBlock)block 25 | { 26 | if ((self = [super init])) { 27 | NSAssert(tweak != nil, @"tweak is required"); 28 | NSAssert(block != NULL, @"block is required"); 29 | 30 | _tweak = tweak; 31 | _block = block; 32 | 33 | [tweak addObserver:self]; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void)tweakDidChange:(MPTweak *)tweak 40 | { 41 | __attribute__((objc_precise_lifetime)) id strongObject = _object; 42 | 43 | if (strongObject != nil) { 44 | _block(strongObject); 45 | } 46 | } 47 | 48 | - (void)attachToObject:(id)object 49 | { 50 | NSAssert(_object == nil, @"can only attach to an object once"); 51 | NSAssert(object != nil, @"object is required"); 52 | 53 | _object = object; 54 | objc_setAssociatedObject(object, (__bridge void *)self, self, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/libMPCategoryHelpers.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/Vendor/Mixpanel/libMPCategoryHelpers.a -------------------------------------------------------------------------------- /ios/Vendor/Mixpanel/test_variant.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "experiment_id": 2, 4 | "actions":[ 5 | {"path": "/UIView/UILabel[text == \"Old Text\"]", "args": [["New Text","NSString"]], "original": [["Old Text","NSString"]], "selector": "setText:", "swizzle":true, "swizzleClass":"UILabel", "swizzleSelector":"didMoveToWindow", "name":"XXXX-XXXX-XXXX"}, 6 | {"path": "/UIView/UILabel[text == \"Old Text 2\"]", "args": [["New Text","NSString"]], "original": [["Old Text 2","NSString"]], "selector": "setText:", "name":"YYYY-YYYY-YYYY"} 7 | ], 8 | "tweaks":[] 9 | } -------------------------------------------------------------------------------- /ios/assets/README: -------------------------------------------------------------------------------- 1 | Place your assets like PNG files in this directory and they will be packaged with your module. 2 | 3 | If you create a file named se.hyperlab.mixpanel.js in this directory, it will be 4 | compiled and used as your module. This allows you to run pure Javascript 5 | modules that are pre-compiled. 6 | 7 | -------------------------------------------------------------------------------- /ios/compile-storyboards.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Staring..." 3 | platform_dir=$(pwd)/platform/iphone 4 | cd $platform_dir 5 | for storyboard_file in *.storyboard; do 6 | if [ -f $storyboard_file ]; then 7 | basename=$(basename "$storyboard_file") 8 | echo " $basename found, staring compilation..." 9 | tmp="/tmp/$basename.$RANDOM.storyboardc" 10 | ibtool --target-device iphone --target-device ipad --errors --warnings --notices --module se.hyperlab.mixpanel --minimum-deployment-target 6.0 --auto-activate-custom-fonts --output-format human-readable-text --compile "${tmp}" "${storyboard_file}" 11 | if [ -f "${storyboard_file}c" ]; then 12 | rm -fr "${storyboard_file}c" 13 | fi 14 | mv $tmp "$platform_dir/${basename}c" 15 | fi 16 | done 17 | echo "Done" -------------------------------------------------------------------------------- /ios/dist/se.hyperlab.mixpanel-iphone-0.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/dist/se.hyperlab.mixpanel-iphone-0.1.zip -------------------------------------------------------------------------------- /ios/dist/se.hyperlab.mixpanel-iphone-0.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/dist/se.hyperlab.mixpanel-iphone-0.2.zip -------------------------------------------------------------------------------- /ios/dist/se.hyperlab.mixpanel-iphone-0.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/dist/se.hyperlab.mixpanel-iphone-0.3.zip -------------------------------------------------------------------------------- /ios/dist/se.hyperlab.mixpanel-iphone-0.4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/dist/se.hyperlab.mixpanel-iphone-0.4.zip -------------------------------------------------------------------------------- /ios/dist/se.hyperlab.mixpanel-iphone-0.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/dist/se.hyperlab.mixpanel-iphone-0.5.zip -------------------------------------------------------------------------------- /ios/dist/se.hyperlab.mixpanel-iphone-0.6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/dist/se.hyperlab.mixpanel-iphone-0.6.zip -------------------------------------------------------------------------------- /ios/dist/se.hyperlab.mixpanel-iphone-0.7.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/dist/se.hyperlab.mixpanel-iphone-0.7.zip -------------------------------------------------------------------------------- /ios/dist/se.hyperlab.mixpanel-iphone-0.8.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/dist/se.hyperlab.mixpanel-iphone-0.8.zip -------------------------------------------------------------------------------- /ios/documentation/index.md: -------------------------------------------------------------------------------- 1 | # TiMixpanel Module 2 | 3 | ## Description 4 | 5 | TODO: Enter your module description here 6 | 7 | ## Accessing the TiMixpanel Module 8 | 9 | To access this module from JavaScript, you would do the following: 10 | 11 | var TiMixpanel = require("se.hyperlab.mixpanel"); 12 | 13 | The TiMixpanel variable is a reference to the Module object. 14 | 15 | ## Reference 16 | 17 | TODO: If your module has an API, you should document 18 | the reference here. 19 | 20 | ### ___PROJECTNAMEASIDENTIFIER__.function 21 | 22 | TODO: This is an example of a module function. 23 | 24 | ### ___PROJECTNAMEASIDENTIFIER__.property 25 | 26 | TODO: This is an example of a module property. 27 | 28 | ## Usage 29 | 30 | TODO: Enter your usage example here 31 | 32 | ## Author 33 | 34 | TODO: Enter your author name, email and other contact 35 | details you want to share here. 36 | 37 | ## License 38 | 39 | TODO: Enter your license/legal information here. 40 | -------------------------------------------------------------------------------- /ios/example/app.js: -------------------------------------------------------------------------------- 1 | // Simple test UI 2 | var win = Ti.UI.createWindow({ 3 | backgroundColor:'white', 4 | top: 0, 5 | bottom: 0, 6 | layout: 'vertical' 7 | }); 8 | var trackEventButton = Ti.UI.createButton({ 9 | top: 20, 10 | title: 'Track event' 11 | }); 12 | var notificationButton = Ti.UI.createButton({ 13 | title: 'Show Notification' 14 | }); 15 | var surveyButton = Ti.UI.createButton({ 16 | title: 'Show Survey' 17 | }); 18 | win.add(trackEventButton); 19 | win.add(notificationButton); 20 | win.add(surveyButton); 21 | win.open(); 22 | 23 | 24 | // Mixpanel test/demo code, mirrors the iOS API fairly well 25 | // See: https://mixpanel.com/help/reference/ios 26 | 27 | var mixpanel = require('se.hyperlab.mixpanel'); 28 | 29 | // The second parameter is optional. showSurveyOnActive and showNotificationOnActive 30 | // are true by default. 31 | mixpanel.initWithToken('YOUR-TOKEN-GOES-HERE', { 32 | showSurveyOnActive: false, 33 | showNotificationOnActive: false 34 | }); 35 | 36 | // Flush queued data every 45 seconds (Instead of the default of 60 seconds) 37 | mixpanel.flushInterval = 45; 38 | 39 | Ti.API.log('Mixpanel distinctId: ' + mixpanel.distinctId); 40 | 41 | // The same as: 42 | // mixpanel.createAliasForId('NEW-TEST-ID', mixpanel.distinctId); 43 | mixpanel.createAlias('NEW-TEST-ID'); 44 | 45 | mixpanel.identify('NEW-TEST-ID'); 46 | Ti.API.log('Mixpanel distinctId: ' + mixpanel.distinctId); 47 | 48 | mixpanel.registerSuperProperties({ 49 | 'Device Model': Ti.Platform.model, 50 | 'Application ID': Ti.App.id 51 | }); 52 | 53 | mixpanel.registerSuperPropertiesOnce({ 54 | 'Affiliate ID': '123abc' 55 | }); 56 | 57 | mixpanel.track('App Opened'); 58 | 59 | // Manually flush data to MixPanel 60 | mixpanel.flush(); 61 | 62 | trackEventButton.addEventListener('click', function () { 63 | mixpanel.track('Custom Event', { 64 | 'Custom Prop': 'value' 65 | }); 66 | }); 67 | notificationButton.addEventListener('click', function () { 68 | mixpanel.showNotification(); 69 | }); 70 | surveyButton.addEventListener('click', function () { 71 | mixpanel.showSurvey(); 72 | }); 73 | 74 | // User Profiles 75 | mixpanel.profileSet({ 76 | '$name': 'Full Name', 77 | '$email': 'test@example.com', 78 | 79 | key: 'value', 80 | special: 'once', 81 | num: 2, 82 | list: ['a'] 83 | }); 84 | mixpanel.profileSetOnce({ 85 | special: 'twice', // Wont update key 86 | }); 87 | 88 | 89 | mixpanel.profileIncrement({ 90 | num: 1 // To a total of 3 91 | }); 92 | mixpanel.profileAppend({ 93 | list: ['b', 'c'] 94 | }); 95 | 96 | mixpanel.profileTrackCharge(150); 97 | mixpanel.profileTrackCharge(100, { 98 | campaign: '123abc' 99 | }); 100 | 101 | 102 | -------------------------------------------------------------------------------- /ios/hooks/README: -------------------------------------------------------------------------------- 1 | These files are not yet supported as of 1.4.0 but will be in a near future release. 2 | -------------------------------------------------------------------------------- /ios/hooks/add.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module project add hook that will be 4 | # called when your module is added to a project 5 | # 6 | import os, sys 7 | 8 | def dequote(s): 9 | if s[0:1] == '"': 10 | return s[1:-1] 11 | return s 12 | 13 | def main(args,argc): 14 | # You will get the following command line arguments 15 | # in the following order: 16 | # 17 | # project_dir = the full path to the project root directory 18 | # project_type = the type of project (desktop, mobile, ipad) 19 | # project_name = the name of the project 20 | # 21 | project_dir = dequote(os.path.expanduser(args[1])) 22 | project_type = dequote(args[2]) 23 | project_name = dequote(args[3]) 24 | 25 | # TODO: write your add hook here (optional) 26 | 27 | 28 | # exit 29 | sys.exit(0) 30 | 31 | 32 | 33 | if __name__ == '__main__': 34 | main(sys.argv,len(sys.argv)) 35 | 36 | -------------------------------------------------------------------------------- /ios/hooks/install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module install hook that will be 4 | # called when your module is first installed 5 | # 6 | import os, sys 7 | 8 | def main(args,argc): 9 | 10 | # TODO: write your install hook here (optional) 11 | 12 | # exit 13 | sys.exit(0) 14 | 15 | 16 | 17 | if __name__ == '__main__': 18 | main(sys.argv,len(sys.argv)) 19 | 20 | -------------------------------------------------------------------------------- /ios/hooks/remove.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module project remove hook that will be 4 | # called when your module is remove from a project 5 | # 6 | import os, sys 7 | 8 | def dequote(s): 9 | if s[0:1] == '"': 10 | return s[1:-1] 11 | return s 12 | 13 | def main(args,argc): 14 | # You will get the following command line arguments 15 | # in the following order: 16 | # 17 | # project_dir = the full path to the project root directory 18 | # project_type = the type of project (desktop, mobile, ipad) 19 | # project_name = the name of the project 20 | # 21 | project_dir = dequote(os.path.expanduser(args[1])) 22 | project_type = dequote(args[2]) 23 | project_name = dequote(args[3]) 24 | 25 | # TODO: write your remove hook here (optional) 26 | 27 | # exit 28 | sys.exit(0) 29 | 30 | 31 | 32 | if __name__ == '__main__': 33 | main(sys.argv,len(sys.argv)) 34 | 35 | -------------------------------------------------------------------------------- /ios/hooks/uninstall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This is the module uninstall hook that will be 4 | # called when your module is uninstalled 5 | # 6 | import os, sys 7 | 8 | def main(args,argc): 9 | 10 | # TODO: write your uninstall hook here (optional) 11 | 12 | # exit 13 | sys.exit(0) 14 | 15 | 16 | if __name__ == '__main__': 17 | main(sys.argv,len(sys.argv)) 18 | 19 | -------------------------------------------------------------------------------- /ios/manifest: -------------------------------------------------------------------------------- 1 | # 2 | # this is your module manifest and used by Titanium 3 | # during compilation, packaging, distribution, etc. 4 | # 5 | version: 0.8 6 | apiversion: 2 7 | description: Mixpanel integration for Titanium Mobile 8 | author: Jonatan Lundin 9 | license: MIT 10 | copyright: Copyright (C) 2014 Hyperlab AB 11 | 12 | 13 | # these should not be edited 14 | name: TiMixpanel 15 | moduleid: se.hyperlab.mixpanel 16 | guid: 534f4d59-d4ea-4f21-bdc0-e9d1858c9c8f 17 | platform: iphone 18 | minsdk: 3.2.2.GA 19 | architectures: armv7 i386 x86_64 arm64 20 | -------------------------------------------------------------------------------- /ios/module.xcconfig: -------------------------------------------------------------------------------- 1 | OTHER_LDFLAGS=$(inherited) -framework SystemConfiguration -framework CoreTelephony -framework Accelerate -framework CoreGraphics -framework QuartzCore 2 | 3 | // 4 | // PLACE ANY BUILD DEFINITIONS IN THIS FILE AND THEY WILL BE 5 | // PICKED UP DURING THE APP BUILD FOR YOUR MODULE 6 | // 7 | // see the following webpage for instructions on the settings 8 | // for this file: 9 | // http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/XcodeBuildSystem/400-Build_Configurations/build_configs.html 10 | // 11 | 12 | // 13 | // How to add a Framework (example) 14 | // 15 | // OTHER_LDFLAGS=$(inherited) -framework Foo 16 | // 17 | // Adding a framework for a specific version(s) of iPhone: 18 | // 19 | // OTHER_LDFLAGS[sdk=iphoneos4*]=$(inherited) -framework Foo 20 | // OTHER_LDFLAGS[sdk=iphonesimulator4*]=$(inherited) -framework Foo 21 | // 22 | // 23 | // How to add a compiler define: 24 | // 25 | // OTHER_CFLAGS=$(inherited) -ObjC -all_load 26 | // 27 | // 28 | // IMPORTANT NOTE: always use $(inherited) in your overrides 29 | // 30 | -------------------------------------------------------------------------------- /ios/platform/README: -------------------------------------------------------------------------------- 1 | You can place platform-specific files here in sub-folders named "android" and/or "iphone", just as you can with normal Titanium Mobile SDK projects. Any folders and files you place here will be merged with the platform-specific files in a Titanium Mobile project that uses this module. 2 | 3 | When a Titanium Mobile project that uses this module is built, the files from this platform/ folder will be treated the same as files (if any) from the Titanium Mobile project's platform/ folder. 4 | -------------------------------------------------------------------------------- /ios/platform/iphone/MPArrowLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPArrowLeft.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPArrowLeft@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPArrowLeft@2x.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPArrowRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPArrowRight.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPArrowRight@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPArrowRight@2x.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPCheckmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPCheckmark.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPCheckmark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPCheckmark@2x.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPCloseBtn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPCloseBtn.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPCloseBtn@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPCloseBtn@2x.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPDismissKeyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPDismissKeyboard.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPDismissKeyboard@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPDismissKeyboard@2x.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPLogo.png -------------------------------------------------------------------------------- /ios/platform/iphone/MPLogo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperlab/TiMixpanel/1533d799c1e37787d229b7a34bd5e1d221f71ebd/ios/platform/iphone/MPLogo@2x.png -------------------------------------------------------------------------------- /ios/timodule.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ios/titanium.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // CHANGE THESE VALUES TO REFLECT THE VERSION (AND LOCATION IF DIFFERENT) 4 | // OF YOUR TITANIUM SDK YOU'RE BUILDING FOR 5 | // 6 | // 7 | TITANIUM_SDK_VERSION = 3.4.1.GA 8 | 9 | 10 | // 11 | // THESE SHOULD BE OK GENERALLY AS-IS 12 | // 13 | TITANIUM_SDK = ~/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION) 14 | TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include" 15 | TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore" 16 | HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) 17 | 18 | 19 | 20 | --------------------------------------------------------------------------------