├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── feature_request.yml │ └── maintainer-blank.yml ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── stale.yml └── workflows │ ├── build-examples.yml │ ├── build.yml │ ├── danger.yml │ ├── lint.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── .periphery.yml ├── .swiftformat ├── .swiftlint.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── Package.resolved ├── Package.swift ├── PostHog.podspec ├── PostHog.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ └── xcschemes │ ├── PostHog.xcscheme │ ├── PostHogExample.xcscheme │ ├── PostHogExampleMacOS.xcscheme │ ├── PostHogExampleStoryboard.xcscheme │ ├── PostHogExampleTvOS.xcscheme │ ├── PostHogExampleWatchOS Watch App.xcscheme │ ├── PostHogExampleWithPods.xcscheme │ ├── PostHogExampleWithSPM.xcscheme │ ├── PostHogObjCExample.xcscheme │ └── PostHogTests.xcscheme ├── PostHog ├── Autocapture │ ├── AutocaptureEventProcessing.swift │ ├── ForwardingPickerViewDelegate.swift │ ├── PostHogAutocaptureEventTracker.swift │ ├── PostHogAutocaptureIntegration.swift │ ├── SwiftUI │ │ └── View+PostHogLabel.swift │ └── UIView+PostHogLabel.swift ├── DI.swift ├── Models │ └── PostHogEvent.swift ├── PostHog.h ├── PostHog.modulemap ├── PostHogApi.swift ├── PostHogBatchUploadInfo.swift ├── PostHogConfig.swift ├── PostHogConsumerPayload.swift ├── PostHogContext.swift ├── PostHogExtensions.swift ├── PostHogFeatureFlags.swift ├── PostHogFileBackedQueue.swift ├── PostHogLegacyQueue.swift ├── PostHogPersonProfiles.swift ├── PostHogPropertiesSanitizer.swift ├── PostHogQueue.swift ├── PostHogSDK.swift ├── PostHogSessionManager.swift ├── PostHogStorage.swift ├── PostHogStorageManager.swift ├── PostHogSwizzler.swift ├── PostHogVersion.swift ├── Replay │ ├── CGColor+Util.swift │ ├── CGSize+Util.swift │ ├── Date+Util.swift │ ├── MethodSwizzler.swift │ ├── NetworkSample.swift │ ├── PostHogReplayIntegration.swift │ ├── PostHogSessionReplayConfig.swift │ ├── RRStyle.swift │ ├── RRWireframe.swift │ ├── String+Util.swift │ ├── UIApplicationTracker.swift │ ├── UIColor+Util.swift │ ├── UIImage+Util.swift │ ├── UITextInputTraits+Util.swift │ ├── UIView+Util.swift │ ├── URLSessionExtension.swift │ ├── URLSessionInterceptor.swift │ ├── URLSessionSwizzler.swift │ ├── ViewLayoutTracker.swift │ └── ViewTreeSnapshotStatus.swift ├── Resources │ └── PrivacyInfo.xcprivacy ├── SwiftUI │ ├── PostHogMaskViewModifier.swift │ ├── PostHogNoMaskViewModifier.swift │ ├── PostHogSwiftUIViewModifiers.swift │ └── PostHogTagViewModifier.swift ├── UIViewController.swift └── Utils │ ├── ApplicationLifecyclePublisher.swift │ ├── AssociatedKeys.swift │ ├── Data+Gzip.swift │ ├── DateUtils.swift │ ├── DictUtils.swift │ ├── Errors.swift │ ├── FileUtils.swift │ ├── Hedgelog.swift │ ├── Reachability.swift │ ├── ReadWriteLock.swift │ ├── TimeBasedEpochGenerator.swift │ ├── UIApplication+.swift │ ├── UIImage+WebP.swift │ ├── UIWindow+.swift │ └── UUIDUtils.swift ├── PostHogExample ├── Api.swift ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── max_static.imageset │ │ ├── Contents.json │ │ └── max_static.png ├── ContentView.swift ├── PostHogExample.entitlements ├── PostHogExampleApp.swift ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json └── Views │ └── UIViewExample.swift ├── PostHogExampleAutocapture ├── LICENSE │ └── LICENSE.txt ├── PostHogExampleAutocapture.xcodeproj │ ├── .xcodesamplecode.plist │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── PostHogExampleAutocapture.xcscheme └── PostHogExampleAutocapture │ ├── ActivityIndicatorViewController.swift │ ├── AlertControllerViewController.swift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── Flowers_1.imageset │ │ ├── Contents.json │ │ └── Flowers_1.png │ ├── Flowers_2.imageset │ │ ├── Contents.json │ │ └── Flowers_2.png │ ├── background.imageset │ │ ├── Contents.json │ │ ├── stepper_and_segment_background_1x.png │ │ ├── stepper_and_segment_background_2x.png │ │ └── stepper_and_segment_background_3x.png │ ├── background_disabled.imageset │ │ ├── Contents.json │ │ ├── stepper_and_segment_background_disabled_1x.png │ │ ├── stepper_and_segment_background_disabled_2x.png │ │ └── stepper_and_segment_background_disabled_3x.png │ ├── background_highlighted.imageset │ │ ├── Contents.json │ │ ├── stepper_and_segment_background_highlighted_1x.png │ │ ├── stepper_and_segment_background_highlighted_2x.png │ │ └── stepper_and_segment_background_highlighted_3x.png │ ├── search_bar_background.imageset │ │ ├── Contents.json │ │ ├── search_bar_background_3x.png │ │ ├── search_bar_bg_1x.png │ │ └── search_bar_bg_2x.png │ ├── slider_blue_track.imageset │ │ ├── Contents.json │ │ ├── slider_blue_track_1x.png │ │ ├── slider_blue_track_2x.png │ │ └── slider_blue_track_3x.png │ ├── slider_green_track.imageset │ │ ├── Contents.json │ │ ├── slider_green_track_1x.png │ │ ├── slider_green_track_2x.png │ │ └── slider_green_track_3x.png │ ├── stepper_and_segment_divider.imageset │ │ ├── Contents.json │ │ ├── stepper_and_segment_divider_3x.png │ │ ├── stepper_and_segment_segment_divider_1x.png │ │ └── stepper_and_segment_segment_divider_2x.png │ ├── text_field_background.imageset │ │ ├── Contents.json │ │ ├── text_field_background_1x.png │ │ ├── text_field_background_2x.png │ │ └── text_field_background_3x.png │ ├── text_field_purple_right_view.imageset │ │ ├── Contents.json │ │ ├── text_field_purple_right_view_1x.png │ │ ├── text_field_purple_right_view_2x.png │ │ └── text_field_purple_right_view_3x.png │ ├── text_view_attachment.imageset │ │ ├── Contents.json │ │ └── Sunset_5.png │ ├── text_view_background.colorset │ │ └── Contents.json │ ├── tinted_segmented_control.colorset │ │ └── Contents.json │ ├── tinted_stepper_control.colorset │ │ └── Contents.json │ └── toolbar_background.imageset │ │ ├── Contents.json │ │ ├── toolbar_background_1x.png │ │ ├── toolbar_background_2x.png │ │ └── toolbar_background_3x.png │ ├── Base.lproj │ ├── ActivityIndicatorViewController.storyboard │ ├── AlertControllerViewController.storyboard │ ├── ButtonViewController.storyboard │ ├── ColorPickerViewController.storyboard │ ├── Credits.rtf │ ├── CustomPageControlViewController.storyboard │ ├── CustomSearchBarViewController.storyboard │ ├── CustomToolbarViewController.storyboard │ ├── DatePickerController.storyboard │ ├── DefaultPageControlViewController.storyboard │ ├── DefaultSearchBarViewController.storyboard │ ├── DefaultToolbarViewController.storyboard │ ├── FontPickerViewController.storyboard │ ├── ImagePickerViewController.storyboard │ ├── ImageViewController.storyboard │ ├── InfoPlist.strings │ ├── LaunchScreen.storyboard │ ├── Localizable.strings │ ├── Main.storyboard │ ├── MenuButtonViewController.storyboard │ ├── PickerViewController.storyboard │ ├── PointerInteractionButtonViewController.storyboard │ ├── ProgressViewController.storyboard │ ├── SegmentedControlViewController.storyboard │ ├── SliderViewController.storyboard │ ├── StackViewController.storyboard │ ├── StepperViewController.storyboard │ ├── SwitchViewController.storyboard │ ├── SymbolViewController.storyboard │ ├── TextFieldViewController.storyboard │ ├── TextViewController.storyboard │ ├── TintedToolbarViewController.storyboard │ ├── VisualEffectViewController.storyboard │ ├── WebViewController.storyboard │ └── content.html │ ├── BaseTableViewController.swift │ ├── ButtonViewController+Configs.swift │ ├── ButtonViewController.swift │ ├── CaseElement.swift │ ├── ColorPickerViewController.swift │ ├── CustomPageControlViewController.swift │ ├── CustomSearchBarViewController.swift │ ├── CustomToolbarViewController.swift │ ├── DatePickerController.swift │ ├── DefaultPageControlViewController.swift │ ├── DefaultSearchBarViewController.swift │ ├── DefaultToolbarViewController.swift │ ├── FontPickerViewController.swift │ ├── ImagePickerViewController.swift │ ├── ImageViewController.swift │ ├── Info.plist │ ├── MenuButtonViewController.swift │ ├── OutlineViewController.swift │ ├── PickerViewController.swift │ ├── PointerInteractionButtonViewController.swift │ ├── ProgressViewController.swift │ ├── SceneDelegate.swift │ ├── SegmentedControlViewController.swift │ ├── SliderViewController.swift │ ├── StackViewController.swift │ ├── StepperViewController.swift │ ├── SwitchViewController.swift │ ├── SymbolViewController.swift │ ├── TextFieldViewController.swift │ ├── TextViewController.swift │ ├── TintedToolbarViewController.swift │ ├── UIKitCatalog │ └── Base.lproj │ │ └── Localizable.stringsdict │ ├── VisualEffectViewController.swift │ └── WebViewController.swift ├── PostHogExampleExternalSDK ├── ExternalSDK.swift ├── ExternalSDK │ └── ExternalSDK.h ├── Package.swift ├── PostHogExampleExternalSDK.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── ExternalSDK.xcscheme ├── SDKClient │ ├── ExternalSDKClient │ │ ├── Assets.xcassets │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── ContentView.swift │ │ ├── ExternalSDKClient.entitlements │ │ ├── ExternalSDKClientApp.swift │ │ └── Preview Content │ │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ └── PostHogExampleExternalSDKClient.xcodeproj │ │ └── project.pbxproj ├── Sources │ └── ExternalSDK-iOS │ │ └── ExternalSDK-iOS.swift └── build_xcframework.sh ├── PostHogExampleMacOS ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── ContentView.swift ├── PostHogExampleMacOS.entitlements ├── PostHogExampleMacOSApp.swift └── Preview Content │ └── Preview Assets.xcassets │ └── Contents.json ├── PostHogExampleStoryboard ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── SceneDelegate.swift └── ViewController.swift ├── PostHogExampleTvOS ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── App Icon & Top Shelf Image.brandassets │ │ ├── App Icon - App Store.imagestack │ │ │ ├── Back.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── Front.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ └── Middle.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ ├── App Icon.imagestack │ │ │ ├── Back.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── Front.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ └── Middle.imagestacklayer │ │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Top Shelf Image Wide.imageset │ │ │ └── Contents.json │ │ └── Top Shelf Image.imageset │ │ │ └── Contents.json │ └── Contents.json ├── ContentView.swift ├── PostHogExampleTvOSApp.swift └── Preview Content │ └── Preview Assets.xcassets │ └── Contents.json ├── PostHogExampleWatchOS ├── PostHogExampleWatchOS Watch App │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── PostHogExampleWatchOSApp.swift │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json └── PostHogExampleWatchOS.xcodeproj │ └── project.pbxproj ├── PostHogExampleWithPods ├── Podfile ├── Podfile.static ├── PostHogExampleWithPods.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── PostHogExampleWithPods.xcscheme ├── PostHogExampleWithPods │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── PostHogExampleWithPodsApp.swift │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json └── README.md ├── PostHogExampleWithSPM ├── .gitignore ├── PostHogExampleWithSPM.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── PostHogExampleWithSPM │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── ContentView.swift │ ├── PostHogExampleWithSPMApp.swift │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json └── README.md ├── PostHogObjCExample ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── SceneDelegate.h ├── SceneDelegate.m ├── ViewController.h ├── ViewController.m └── main.m ├── PostHogTests ├── ExampleSanitizer.swift ├── PostHogApiTest.swift ├── PostHogAutocaptureEventTrackerSpec.swift ├── PostHogAutocaptureIntegrationSpec.swift ├── PostHogConfigTest.swift ├── PostHogContextTest.swift ├── PostHogFeatureFlagsTest.swift ├── PostHogFileBackedQueueTest.swift ├── PostHogLegacyQueueTest.swift ├── PostHogQueueTest.swift ├── PostHogSDKPersonProfilesTest.swift ├── PostHogSDKTest.swift ├── PostHogSessionManagerTest.swift ├── PostHogStorageManagerTest.swift ├── PostHogStorageTest.swift ├── PostHogWebPTest.swift ├── Resources │ ├── input_1.png │ ├── input_2.png │ ├── input_3.png │ ├── output_1.webp │ ├── output_2.webp │ └── output_3.webp ├── TestUtils │ ├── MockPostHogServer.swift │ ├── TestError.swift │ ├── TestPostHog.swift │ └── URLSession+body.swift └── UUIDTest.swift ├── README.md ├── RELEASING.md ├── USAGE.md ├── dangerfile.js ├── scripts ├── bump-version.sh ├── commit-code.sh ├── create-tag.sh ├── prepare-release.sh └── update-tag.sh └── vendor └── libwebp ├── COPYING ├── PATENTS ├── alpha_enc.c ├── alpha_processing.c ├── alpha_processing_neon.c ├── alpha_processing_sse2.c ├── alpha_processing_sse41.c ├── analysis_enc.c ├── backward_references_cost_enc.c ├── backward_references_enc.c ├── backward_references_enc.h ├── bit_reader_utils.c ├── bit_reader_utils.h ├── bit_writer_utils.c ├── bit_writer_utils.h ├── color_cache_utils.c ├── color_cache_utils.h ├── common_dec.h ├── common_sse2.h ├── common_sse41.h ├── config_enc.c ├── cost.c ├── cost_enc.c ├── cost_enc.h ├── cost_neon.c ├── cost_sse2.c ├── cpu.c ├── cpu.h ├── dec.c ├── dec_clip_tables.c ├── dec_neon.c ├── dec_sse2.c ├── dec_sse41.c ├── decode.h ├── dsp.h ├── enc.c ├── enc_neon.c ├── enc_sse2.c ├── enc_sse41.c ├── encode.h ├── endian_inl_utils.h ├── filter_enc.c ├── filters.c ├── filters_neon.c ├── filters_sse2.c ├── filters_utils.c ├── filters_utils.h ├── format_constants.h ├── frame_enc.c ├── histogram_enc.c ├── histogram_enc.h ├── huffman_encode_utils.c ├── huffman_encode_utils.h ├── huffman_utils.c ├── huffman_utils.h ├── iterator_enc.c ├── lossless.c ├── lossless.h ├── lossless_common.h ├── lossless_enc.c ├── lossless_enc_neon.c ├── lossless_enc_sse2.c ├── lossless_enc_sse41.c ├── lossless_neon.c ├── lossless_sse2.c ├── lossless_sse41.c ├── mux.h ├── mux_types.h ├── muxedit.c ├── muxi.h ├── muxinternal.c ├── muxread.c ├── near_lossless_enc.c ├── neon.h ├── palette.c ├── palette.h ├── picture_csp_enc.c ├── picture_enc.c ├── picture_psnr_enc.c ├── picture_rescale_enc.c ├── picture_tools_enc.c ├── predictor_enc.c ├── quant.h ├── quant_enc.c ├── quant_levels_dec_utils.c ├── quant_levels_utils.c ├── quant_levels_utils.h ├── random_utils.c ├── random_utils.h ├── rescaler.c ├── rescaler_neon.c ├── rescaler_sse2.c ├── rescaler_utils.c ├── rescaler_utils.h ├── sharpyuv.c ├── sharpyuv.h ├── sharpyuv_cpu.c ├── sharpyuv_cpu.h ├── sharpyuv_csp.c ├── sharpyuv_csp.h ├── sharpyuv_dsp.c ├── sharpyuv_dsp.h ├── sharpyuv_gamma.c ├── sharpyuv_gamma.h ├── sharpyuv_neon.c ├── sharpyuv_sse2.c ├── ssim.c ├── ssim_sse2.c ├── syntax_enc.c ├── thread_utils.c ├── thread_utils.h ├── token_enc.c ├── tree_enc.c ├── types.h ├── upsampling.c ├── upsampling_neon.c ├── upsampling_sse2.c ├── upsampling_sse41.c ├── utils.c ├── utils.h ├── vp8_dec.h ├── vp8i_dec.h ├── vp8i_enc.h ├── vp8l_enc.c ├── vp8li_dec.h ├── vp8li_enc.h ├── webp_enc.c ├── webpi_dec.h ├── yuv.c ├── yuv.h ├── yuv_neon.c ├── yuv_sse2.c └── yuv_sse41.c /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @marandaneto 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug Report 2 | description: Tell us about something that's not working the way we (probably) intend. 3 | labels: ["Platform: iOS", "bug"] 4 | body: 5 | 6 | 7 | - type: input 8 | id: version 9 | attributes: 10 | label: Version 11 | description: SDK Version 12 | placeholder: 3.0.0 ← should look like this 13 | validations: 14 | required: true 15 | 16 | - type: textarea 17 | id: repro 18 | attributes: 19 | label: Steps to Reproduce 20 | description: How can we see what you're seeing? Specific is terrific. 21 | placeholder: |- 22 | 1. foo 23 | 2. bar 24 | 3. baz 25 | validations: 26 | required: true 27 | 28 | - type: textarea 29 | id: expected 30 | attributes: 31 | label: Expected Result 32 | validations: 33 | required: true 34 | 35 | - type: textarea 36 | id: actual 37 | attributes: 38 | label: Actual Result 39 | description: Logs? Screenshots? Yes, please. 40 | validations: 41 | required: true 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Ask in the forums 4 | url: https://posthog.com/questions 5 | about: A place to ask questions. 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: 💡 Feature Request 2 | description: Tell us about a problem our SDK could solve but doesn't. 3 | labels: ["enhancement"] 4 | body: 5 | - type: textarea 6 | id: problem 7 | attributes: 8 | label: Problem Statement 9 | description: What problem could we solve that it doesn't? 10 | placeholder: |- 11 | I want to make whirled peas, but it doesn't blend. 12 | validations: 13 | required: true 14 | 15 | - type: textarea 16 | id: expected 17 | attributes: 18 | label: Solution Brainstorm 19 | description: We know you have bright ideas to share ... share away, friend. 20 | placeholder: |- 21 | Add a blender to it. 22 | validations: 23 | required: false 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/maintainer-blank.yml: -------------------------------------------------------------------------------- 1 | name: Blank Issue 2 | description: Blank Issue. Reserved for maintainers. 3 | body: 4 | - type: textarea 5 | id: description 6 | attributes: 7 | label: Description 8 | description: Please describe the issue. 9 | validations: 10 | required: true 11 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## :bulb: Motivation and Context 2 | 3 | 4 | 5 | 6 | ## :green_heart: How did you test it? 7 | 8 | 9 | ## :pencil: Checklist 10 | 11 | 12 | - [ ] I reviewed the submitted code. 13 | - [ ] I added tests to verify the changes. 14 | - [ ] I updated the docs if needed. 15 | - [ ] No breaking change or entry added to the changelog. 16 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | daysUntilStale: 60 2 | daysUntilClose: 7 3 | exemptLabels: 4 | - pinned 5 | - security 6 | staleLabel: wontfix 7 | # Comment to post when marking an issue as stale. Set to `false` to disable 8 | markComment: > 9 | This issue has been automatically marked as stale because it has not had 10 | recent activity. It will be closed if no further activity occurs. Thank you 11 | for your contributions. 12 | closeComment: true 13 | -------------------------------------------------------------------------------- /.github/workflows/build-examples.yml: -------------------------------------------------------------------------------- 1 | name: Build Examples 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | paths-ignore: 8 | - "**/*.md" 9 | jobs: 10 | build: 11 | runs-on: macos-14 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: maxim-lobanov/setup-xcode@v1 15 | with: 16 | xcode-version: latest-stable 17 | - name: Build Example 18 | run: make buildExamples 19 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | paths-ignore: 8 | - "**/*.md" 9 | jobs: 10 | build: 11 | runs-on: macos-14 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: maxim-lobanov/setup-xcode@v1 15 | with: 16 | xcode-version: latest-stable 17 | - name: Build SDK 18 | run: make buildSdk 19 | -------------------------------------------------------------------------------- /.github/workflows/danger.yml: -------------------------------------------------------------------------------- 1 | name: "Danger" 2 | on: 3 | pull_request: 4 | types: [opened, synchronize, reopened, edited, ready_for_review] 5 | 6 | jobs: 7 | build: 8 | name: Changelog 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | with: 13 | fetch-depth: 0 14 | - run: npx danger ci 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | paths-ignore: 8 | - "**/*.md" 9 | jobs: 10 | lint: 11 | runs-on: macos-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Bootstrap 16 | run: make bootstrap 17 | 18 | - name: Run lints 19 | run: make lint 20 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: 'Release' 2 | on: 3 | release: 4 | # runs for stable and pre-releases 5 | types: [published] 6 | 7 | jobs: 8 | cancel-previous-workflow: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Cancel Previous Runs 12 | uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # pin@0.12.1 13 | with: 14 | access_token: ${{ github.token }} 15 | 16 | release: 17 | name: Release 18 | runs-on: macos-14 19 | env: 20 | COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} # Using Manoel's token for now 21 | 22 | steps: 23 | - name: Git checkout 24 | uses: actions/checkout@v4 25 | - uses: maxim-lobanov/setup-xcode@v1 26 | with: 27 | xcode-version: '16.2' 28 | 29 | - name: Bootstrap 30 | run: make bootstrap 31 | 32 | - name: Release 33 | run: make releaseCocoaPods 34 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | paths-ignore: 8 | - "**/*.md" 9 | jobs: 10 | test: 11 | runs-on: macos-14 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: maxim-lobanov/setup-xcode@v1 15 | with: 16 | xcode-version: latest-stable 17 | - name: Test SDK 18 | run: make test -------------------------------------------------------------------------------- /.periphery.yml: -------------------------------------------------------------------------------- 1 | retain_public: true 2 | targets: 3 | - PostHog 4 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | excluded: # case-sensitive paths to ignore during linting. Takes precedence over `included` 2 | - PostHogExample 3 | - PostHogExampleWithSPM 4 | - PostHogExampleAutocapture 5 | - PostHogTests 6 | - PostHog/Utils/ReadWriteLock.swift 7 | - PostHog/Utils/Reachability.swift 8 | - PostHog/Utils/Data+Gzip.swift 9 | - .build 10 | - Pods 11 | 12 | disabled_rules: 13 | - force_cast 14 | - todo 15 | - trailing_comma 16 | - opening_brace 17 | 18 | line_length: 19 | warning: 160 20 | ignores_comments: true 21 | excluded_lines_patterns: [ 22 | # long deprecation messages 23 | \@available(.*/*deprecated.*) 24 | ] 25 | 26 | file_length: 27 | warning: 1000 28 | error: 1200 29 | 30 | identifier_name: 31 | excluded: 32 | - id 33 | - ^ph_.*$ 34 | 35 | function_body_length: 36 | - 1000 # warning 37 | - 1200 # error 38 | 39 | type_body_length: 40 | - 1000 # warning 41 | - 1200 # error 42 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | If you would like to contribute code to `posthog-ios` you can do so through 4 | GitHub by forking the repository and opening a pull request against `main`. 5 | 6 | ## Development Guide 7 | 8 | 1. Install Xcode 9 | 2. Open the **file** `PostHog.xcodeproj` project in Xcode 10 | 3. Run `make bootstrap` to install all dependencies. 11 | 12 | When submitting code, please make every effort to follow existing conventions 13 | and style in order to keep the code as readable as possible. Please also make 14 | sure your code compiles by `make build`. In addition please consider adding 15 | unit tests covering your change, this will make your change much more likely to be accepted 16 | 17 | Above all, thank you for contributing! 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2023] [PostHog] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "CwlCatchException", 6 | "repositoryURL": "https://github.com/mattgallagher/CwlCatchException.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "3ef6999c73b6938cc0da422f2c912d0158abb0a0", 10 | "version": "2.2.0" 11 | } 12 | }, 13 | { 14 | "package": "CwlPreconditionTesting", 15 | "repositoryURL": "https://github.com/mattgallagher/CwlPreconditionTesting.git", 16 | "state": { 17 | "branch": null, 18 | "revision": "2ef56b2caf25f55fa7eef8784c30d5a767550f54", 19 | "version": "2.2.1" 20 | } 21 | }, 22 | { 23 | "package": "Nimble", 24 | "repositoryURL": "https://github.com/Quick/Nimble.git", 25 | "state": { 26 | "branch": null, 27 | "revision": "edaedc1ec86f14ac6e2ca495b94f0ff7150d98d0", 28 | "version": "12.3.0" 29 | } 30 | }, 31 | { 32 | "package": "OHHTTPStubs", 33 | "repositoryURL": "https://github.com/AliSoftware/OHHTTPStubs.git", 34 | "state": { 35 | "branch": null, 36 | "revision": "12f19662426d0434d6c330c6974d53e2eb10ecd9", 37 | "version": "9.1.0" 38 | } 39 | }, 40 | { 41 | "package": "Quick", 42 | "repositoryURL": "https://github.com/Quick/Quick.git", 43 | "state": { 44 | "branch": null, 45 | "revision": "16910e406be96e08923918315388c3e989deac9e", 46 | "version": "6.1.0" 47 | } 48 | } 49 | ] 50 | }, 51 | "version": 1 52 | } 53 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "PostHog", 6 | platforms: [ 7 | // TODO: add .visionOS(.v1), when SPM is >= 5.9 8 | .macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6), 9 | ], 10 | products: [ 11 | // Products define the executables and libraries a package produces, and make them visible to other packages. 12 | .library( 13 | name: "PostHog", 14 | targets: ["PostHog"] 15 | ), 16 | ], 17 | dependencies: [ 18 | // Dependencies declare other packages that this package depends on. 19 | .package(url: "https://github.com/Quick/Quick.git", from: "6.0.0"), 20 | .package(url: "https://github.com/Quick/Nimble.git", from: "12.0.0"), 21 | .package(url: "https://github.com/AliSoftware/OHHTTPStubs.git", from: "9.0.0"), 22 | ], 23 | targets: [ 24 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 25 | // Targets can depend on other targets in this package, and on products in packages this package depends on. 26 | .target( 27 | name: "PostHog", 28 | dependencies: ["phlibwebp"], 29 | path: "PostHog", 30 | resources: [ 31 | .copy("Resources/PrivacyInfo.xcprivacy"), 32 | ] 33 | ), 34 | .target( 35 | name: "phlibwebp", 36 | path: "vendor/libwebp", 37 | publicHeadersPath: ".", 38 | cSettings: [ 39 | .headerSearchPath("."), 40 | ] 41 | ), 42 | .testTarget( 43 | name: "PostHogTests", 44 | dependencies: [ 45 | "PostHog", 46 | "Quick", 47 | "Nimble", 48 | "OHHTTPStubs", 49 | .product(name: "OHHTTPStubsSwift", package: "OHHTTPStubs"), 50 | ], 51 | path: "PostHogTests", 52 | resources: [ 53 | .process("Resources"), 54 | ] 55 | ), 56 | ] 57 | ) 58 | -------------------------------------------------------------------------------- /PostHog.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "PostHog" 3 | s.version = "3.19.3" 4 | s.summary = "The hassle-free way to add posthog to your iOS app." 5 | 6 | s.description = <<-DESC 7 | PostHog for iOS provides a single API that lets you 8 | integrate with over 100s of tools. 9 | DESC 10 | 11 | s.homepage = "http://posthog.com/" 12 | s.license = { :type => 'MIT' } 13 | s.author = { "PostHog" => "engineering@posthog.com" } 14 | s.source = { :git => "https://github.com/PostHog/posthog-ios.git", :tag => s.version.to_s } 15 | s.social_media_url = 'https://twitter.com/PostHog' 16 | s.readme = "https://raw.githubusercontent.com/PostHog/posthog-ios/#{s.version.to_s}/README.md" 17 | s.changelog = "https://raw.githubusercontent.com/PostHog/posthog-ios/#{s.version.to_s}/CHANGELOG.md" 18 | 19 | s.ios.deployment_target = '13.0' 20 | s.tvos.deployment_target = '13.0' 21 | s.osx.deployment_target = "10.15" 22 | s.watchos.deployment_target = "6.0" 23 | s.visionos.deployment_target = "1.0" 24 | s.swift_versions = "5.3" 25 | 26 | s.frameworks = 'Foundation' 27 | 28 | s.source_files = [ 29 | 'PostHog/**/*.{swift,h,hpp,m,mm,c,cpp}', 30 | 'vendor/libwebp/**/*.{h,c}' 31 | ] 32 | s.resource_bundles = { "PostHog" => "PostHog/Resources/PrivacyInfo.xcprivacy" } 33 | end 34 | -------------------------------------------------------------------------------- /PostHog.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PostHog.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /PostHog.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /PostHog/Autocapture/AutocaptureEventProcessing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AutocaptureEventProcessing.swift 3 | // PostHog 4 | // 5 | // Created by Yiannis Josephides on 30/10/2024. 6 | // 7 | 8 | #if os(iOS) || targetEnvironment(macCatalyst) 9 | import Foundation 10 | 11 | protocol AutocaptureEventProcessing: AnyObject { 12 | func process(source: PostHogAutocaptureEventTracker.EventSource, event: PostHogAutocaptureEventTracker.EventData) 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /PostHog/Autocapture/UIView+PostHogLabel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+PostHogLabel.swift 3 | // PostHog 4 | // 5 | // Created by Yiannis Josephides on 04/12/2024. 6 | // 7 | 8 | #if os(iOS) || targetEnvironment(macCatalyst) 9 | import UIKit 10 | 11 | public extension UIView { 12 | /** 13 | Adds a custom label to this view for use with PostHog's auto-capture functionality. 14 | 15 | By setting a custom label, you can easily identify and filter interactions with this specific element in your analytics data. 16 | 17 | ### Usage 18 | ```swift 19 | let myView = UIView() 20 | myView.postHogLabel = "customLabel" 21 | ``` 22 | */ 23 | var postHogLabel: String? { 24 | get { objc_getAssociatedObject(self, &AssociatedKeys.phLabel) as? String } 25 | set { objc_setAssociatedObject(self, &AssociatedKeys.phLabel, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } 26 | } 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /PostHog/DI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DI.swift 3 | // PostHog 4 | // 5 | // Created by Yiannis Josephides on 17/12/2024. 6 | // 7 | 8 | // swiftlint:disable:next type_name 9 | enum DI { 10 | static var main = Container() 11 | 12 | final class Container { 13 | lazy var appLifecyclePublisher: AppLifecyclePublishing = ApplicationLifecyclePublisher.shared 14 | lazy var sessionManager: PostHogSessionManager = .init() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PostHog/PostHog.h: -------------------------------------------------------------------------------- 1 | // 2 | // PostHog.h 3 | // PostHog 4 | // 5 | // Created by Ben White on 10.01.23. 6 | // 7 | 8 | #import 9 | 10 | //! Project version number for PostHog. 11 | FOUNDATION_EXPORT double PostHogVersionNumber; 12 | 13 | //! Project version string for PostHog. 14 | FOUNDATION_EXPORT const unsigned char PostHogVersionString[]; 15 | 16 | // In this header, you should import all the public headers of your framework using statements like #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | #import 23 | #import 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | #import 34 | #import 35 | #import 36 | #import 37 | #import 38 | #import 39 | #import 40 | #import 41 | #import 42 | #import 43 | #import 44 | #import 45 | #import 46 | #import 47 | #import 48 | #import 49 | #import 50 | #import 51 | #import 52 | #import 53 | #import 54 | #import 55 | #import 56 | #import 57 | #import 58 | #import 59 | #import 60 | #import 61 | -------------------------------------------------------------------------------- /PostHog/PostHog.modulemap: -------------------------------------------------------------------------------- 1 | framework module PostHog { 2 | umbrella header "PostHog.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /PostHog/PostHogBatchUploadInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogBatchUploadInfo.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 13.10.23. 6 | // 7 | 8 | import Foundation 9 | 10 | struct PostHogBatchUploadInfo { 11 | let statusCode: Int? 12 | let error: Error? 13 | } 14 | -------------------------------------------------------------------------------- /PostHog/PostHogConsumerPayload.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogConsumerPayload.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 13.10.23. 6 | // 7 | 8 | import Foundation 9 | 10 | struct PostHogConsumerPayload { 11 | let events: [PostHogEvent] 12 | let completion: (Bool) -> Void 13 | } 14 | -------------------------------------------------------------------------------- /PostHog/PostHogExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogExtensions.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 13.10.23. 6 | // 7 | 8 | import Foundation 9 | 10 | /** 11 | # Notifications 12 | 13 | This helper module encapsulates all notifications that we trigger from within the SDK. 14 | 15 | */ 16 | 17 | public extension PostHogSDK { 18 | @objc static let didStartNotification = Notification.Name("PostHogDidStart") // object: nil 19 | @objc static let didReceiveFeatureFlags = Notification.Name("PostHogDidReceiveFeatureFlags") // object: nil 20 | } 21 | -------------------------------------------------------------------------------- /PostHog/PostHogLegacyQueue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogLegacyQueue.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 30.10.23. 6 | // 7 | 8 | import Foundation 9 | 10 | // Migrates the Old Queue (v2) to the new Queue (v3) 11 | func migrateOldQueue(queue: URL, oldQueue: URL) { 12 | if !FileManager.default.fileExists(atPath: oldQueue.path) { 13 | return 14 | } 15 | 16 | defer { 17 | deleteSafely(oldQueue) 18 | } 19 | 20 | do { 21 | let data = try Data(contentsOf: oldQueue) 22 | let array = try JSONSerialization.jsonObject(with: data) as? [Any] 23 | 24 | if array == nil { 25 | return 26 | } 27 | 28 | for item in array! { 29 | guard let event = item as? [String: Any] else { 30 | continue 31 | } 32 | let timestamp = event["timestamp"] as? String ?? toISO8601String(Date()) 33 | 34 | let timestampDate = toISO8601Date(timestamp) ?? Date() 35 | 36 | let filename = "\(timestampDate.timeIntervalSince1970)" 37 | 38 | let contents = try JSONSerialization.data(withJSONObject: event) 39 | 40 | try contents.write(to: queue.appendingPathComponent(filename)) 41 | } 42 | } catch { 43 | hedgeLog("Failed to migrate queue \(error)") 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /PostHog/PostHogPersonProfiles.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogPersonProfiles.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 09.09.24. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Determines the behavior for processing user profiles. 11 | /// - `never`: We won't process persons for any event. This means that anonymous users will not be merged once 12 | /// they sign up or login, so you lose the ability to create funnels that track users from anonymous to identified. 13 | /// All events (including `$identify`) will be sent with `$process_person_profile: False`. 14 | /// - `always`: We will process persons data for all events. 15 | /// - `identifiedOnly`: (default): we will only process persons when you call `identify`, `alias`, and `group`, Anonymous users won't get person profiles. 16 | @objc(PostHogPersonProfiles) public enum PostHogPersonProfiles: Int { 17 | case never 18 | case always 19 | case identifiedOnly 20 | } 21 | -------------------------------------------------------------------------------- /PostHog/PostHogPropertiesSanitizer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogPropertiesSanitizer.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 06.08.24. 6 | // 7 | 8 | import Foundation 9 | 10 | /// Protocol to sanitize the event properties 11 | @objc(PostHogPropertiesSanitizer) public protocol PostHogPropertiesSanitizer { 12 | /// Sanitizes the event properties 13 | /// - Parameter properties: the event properties to sanitize 14 | /// - Returns: the sanitized properties 15 | /// 16 | /// Obs: `inout` cannot be used in Swift protocols, so you need to clone the properties 17 | /// 18 | /// ```swift 19 | /// private class ExampleSanitizer: PostHogPropertiesSanitizer { 20 | /// public func sanitize(_ properties: [String: Any]) -> [String: Any] { 21 | /// var sanitizedProperties = properties 22 | /// // Perform sanitization 23 | /// // For example, removing keys with empty values 24 | /// for (key, value) in properties { 25 | /// if let stringValue = value as? String, stringValue.isEmpty { 26 | /// sanitizedProperties.removeValue(forKey: key) 27 | /// } 28 | /// } 29 | /// return sanitizedProperties 30 | /// } 31 | /// } 32 | /// ``` 33 | @objc func sanitize(_ properties: [String: Any]) -> [String: Any] 34 | } 35 | -------------------------------------------------------------------------------- /PostHog/PostHogSwizzler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogSwizzler.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 26.03.24. 6 | // 7 | 8 | import Foundation 9 | 10 | func swizzle(forClass: AnyClass, original: Selector, new: Selector) { 11 | guard let originalMethod = class_getInstanceMethod(forClass, original) else { return } 12 | guard let swizzledMethod = class_getInstanceMethod(forClass, new) else { return } 13 | method_exchangeImplementations(originalMethod, swizzledMethod) 14 | } 15 | -------------------------------------------------------------------------------- /PostHog/PostHogVersion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogVersion.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 13.10.23. 6 | // 7 | 8 | import Foundation 9 | 10 | // if you change this, make sure to also change it in the podspec and check if the script scripts/bump-version.sh still works 11 | // This property is internal only 12 | public var postHogVersion = "3.19.3" 13 | 14 | public let postHogiOSSdkName = "posthog-ios" 15 | // This property is internal only 16 | public var postHogSdkName = postHogiOSSdkName 17 | -------------------------------------------------------------------------------- /PostHog/Replay/CGColor+Util.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGColor+Util.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 21.03.24. 6 | // 7 | 8 | #if os(iOS) 9 | 10 | import Foundation 11 | import UIKit 12 | 13 | extension CGColor { 14 | func toRGBString() -> String? { 15 | // see dicussion: https://github.com/PostHog/posthog-ios/issues/226 16 | // Allow only CGColors with an intiialized value of `numberOfComponents` with a value in 3...4 range 17 | // Loading dynamic colors from storyboard sometimes leads to some random values for numberOfComponents like `105553118884896` which crashes the app 18 | guard 19 | 3 ... 4 ~= numberOfComponents, // check range 20 | let components = components, // we now assume it's safe to access `components` 21 | components.count >= 3 22 | else { 23 | return nil 24 | } 25 | 26 | let red = Int(components[0] * 255) 27 | let green = Int(components[1] * 255) 28 | let blue = Int(components[2] * 255) 29 | 30 | return String(format: "#%02X%02X%02X", red, green, blue) 31 | } 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /PostHog/Replay/CGSize+Util.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGSize+Util.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 24.07.24. 6 | // 7 | 8 | #if os(iOS) 9 | import Foundation 10 | 11 | extension CGSize { 12 | func hasSize() -> Bool { 13 | if width == 0 || height == 0 { 14 | return false 15 | } 16 | return true 17 | } 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /PostHog/Replay/Date+Util.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Date+Util.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 21.03.24. 6 | // 7 | 8 | import Foundation 9 | 10 | extension Date { 11 | func toMillis() -> Int64 { 12 | Int64(timeIntervalSince1970 * 1000) 13 | } 14 | } 15 | 16 | public func dateToMillis(_ date: Date) -> Int64 { 17 | date.toMillis() 18 | } 19 | -------------------------------------------------------------------------------- /PostHog/Replay/NetworkSample.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkSample.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 26.03.24. 6 | // 7 | 8 | #if os(iOS) 9 | import Foundation 10 | 11 | struct NetworkSample { 12 | let sessionId: String 13 | let timeOrigin: Date 14 | let entryType = "resource" 15 | var name: String? 16 | var responseStatus: Int? 17 | var initiatorType = "fetch" 18 | var httpMethod: String? 19 | var duration: Int64? 20 | var decodedBodySize: Int64? 21 | 22 | init(sessionId: String, timeOrigin: Date, url: String? = nil) { 23 | self.timeOrigin = timeOrigin 24 | self.sessionId = sessionId 25 | name = url 26 | } 27 | 28 | func toDict() -> [String: Any] { 29 | var dict: [String: Any] = [ 30 | "timestamp": timeOrigin.toMillis(), 31 | "entryType": entryType, 32 | "initiatorType": initiatorType, 33 | ] 34 | 35 | if let name = name { 36 | dict["name"] = name 37 | } 38 | 39 | if let responseStatus = responseStatus { 40 | dict["responseStatus"] = responseStatus 41 | } 42 | 43 | if let httpMethod = httpMethod { 44 | dict["method"] = httpMethod 45 | } 46 | 47 | if let duration = duration { 48 | dict["duration"] = duration 49 | } 50 | 51 | if let decodedBodySize = decodedBodySize { 52 | dict["transferSize"] = decodedBodySize 53 | } 54 | 55 | return dict 56 | } 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /PostHog/Replay/String+Util.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Util.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 21.03.24. 6 | // 7 | 8 | import Foundation 9 | 10 | extension String { 11 | func mask() -> String { 12 | String(repeating: "*", count: count) 13 | } 14 | } 15 | 16 | extension Optional where Wrapped == String { 17 | var isNilOrEmpty: Bool { 18 | (self ?? "").isEmpty 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /PostHog/Replay/UIColor+Util.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Util.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 21.03.24. 6 | // 7 | #if os(iOS) 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIColor { 13 | func toRGBString() -> String? { 14 | cgColor.toRGBString() 15 | } 16 | } 17 | #endif 18 | -------------------------------------------------------------------------------- /PostHog/Replay/UIImage+Util.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Util.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 27.11.24. 6 | // 7 | 8 | #if os(iOS) 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIImage { 13 | func toBase64(_ compressionQuality: CGFloat = 0.3) -> String? { 14 | toWebPBase64(compressionQuality) ?? toJpegBase64(compressionQuality) 15 | } 16 | 17 | private func toWebPBase64(_ compressionQuality: CGFloat) -> String? { 18 | webpData(compressionQuality: compressionQuality).map { data in 19 | "data:image/webp;base64,\(data.base64EncodedString())" 20 | } 21 | } 22 | 23 | private func toJpegBase64(_ compressionQuality: CGFloat) -> String? { 24 | jpegData(compressionQuality: compressionQuality).map { data in 25 | "data:image/jpeg;base64,\(data.base64EncodedString())" 26 | } 27 | } 28 | } 29 | 30 | public func imageToBase64(_ image: UIImage, _ compressionQuality: CGFloat = 0.3) -> String? { 31 | image.toBase64(compressionQuality) 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /PostHog/Replay/UITextInputTraits+Util.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITextInputTraits+Util.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 21.03.24. 6 | // 7 | 8 | #if os(iOS) 9 | import Foundation 10 | import UIKit 11 | 12 | private let sensibleTypes: [UITextContentType] = [ 13 | .newPassword, .oneTimeCode, .creditCardNumber, 14 | .telephoneNumber, .emailAddress, .password, 15 | .username, .URL, .name, .nickname, 16 | .middleName, .familyName, .nameSuffix, 17 | .namePrefix, .organizationName, .location, 18 | .fullStreetAddress, .streetAddressLine1, 19 | .streetAddressLine2, .addressCity, .addressState, 20 | .addressCityAndState, .postalCode, 21 | ] 22 | 23 | extension UITextInputTraits { 24 | func isSensitiveText() -> Bool { 25 | if isSecureTextEntry ?? false { 26 | return true 27 | } 28 | 29 | if let contentType = textContentType, let contentType = contentType { 30 | return sensibleTypes.contains(contentType) 31 | } 32 | 33 | return false 34 | } 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /PostHog/Replay/ViewLayoutTracker.swift: -------------------------------------------------------------------------------- 1 | #if os(iOS) 2 | import Foundation 3 | import UIKit 4 | 5 | enum ViewLayoutTracker { 6 | private(set) static var hasChanges = false 7 | private static var hasSwizzled = false 8 | 9 | static func viewDidLayout(view _: UIView) { 10 | hasChanges = true 11 | } 12 | 13 | static func clear() { 14 | hasChanges = false 15 | } 16 | 17 | static func swizzleLayoutSubviews() { 18 | if hasSwizzled { 19 | return 20 | } 21 | swizzle(forClass: UIView.self, 22 | original: #selector(UIView.layoutSubviews), 23 | new: #selector(UIView.layoutSubviewsOverride)) 24 | hasSwizzled = true 25 | } 26 | 27 | static func unSwizzleLayoutSubviews() { 28 | if !hasSwizzled { 29 | return 30 | } 31 | swizzle(forClass: UIView.self, 32 | original: #selector(UIView.layoutSubviews), 33 | new: #selector(UIView.layoutSubviewsOverride)) 34 | hasSwizzled = false 35 | } 36 | } 37 | 38 | extension UIView { 39 | @objc func layoutSubviewsOverride() { 40 | guard Thread.isMainThread else { 41 | return 42 | } 43 | layoutSubviewsOverride() 44 | ViewLayoutTracker.viewDidLayout(view: self) 45 | } 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /PostHog/Replay/ViewTreeSnapshotStatus.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewTreeSnapshotStatus.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 20.03.24. 6 | // 7 | 8 | import Foundation 9 | 10 | class ViewTreeSnapshotStatus { 11 | var sentFullSnapshot: Bool = false 12 | var sentMetaEvent: Bool = false 13 | var keyboardVisible: Bool = false 14 | var lastSnapshot: Bool = false 15 | } 16 | -------------------------------------------------------------------------------- /PostHog/Resources/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyCollectedDataTypes 6 | 7 | 8 | NSPrivacyCollectedDataType 9 | NSPrivacyCollectedDataTypeProductInteraction 10 | NSPrivacyCollectedDataTypeLinked 11 | 12 | NSPrivacyCollectedDataTypeTracking 13 | 14 | NSPrivacyCollectedDataTypePurposes 15 | 16 | NSPrivacyCollectedDataTypePurposeAnalytics 17 | 18 | 19 | 20 | NSPrivacyCollectedDataType 21 | NSPrivacyCollectedDataTypeOtherUsageData 22 | NSPrivacyCollectedDataTypeLinked 23 | 24 | NSPrivacyCollectedDataTypeTracking 25 | 26 | NSPrivacyCollectedDataTypePurposes 27 | 28 | NSPrivacyCollectedDataTypePurposeAnalytics 29 | 30 | 31 | 32 | NSPrivacyAccessedAPITypes 33 | 34 | 35 | NSPrivacyAccessedAPIType 36 | NSPrivacyAccessedAPICategoryUserDefaults 37 | NSPrivacyAccessedAPITypeReasons 38 | 39 | CA92.1 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /PostHog/SwiftUI/PostHogMaskViewModifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogMaskViewModifier.swift 3 | // PostHog 4 | // 5 | // Created by Yiannis Josephides on 09/10/2024. 6 | // 7 | 8 | #if os(iOS) && canImport(SwiftUI) 9 | 10 | import SwiftUI 11 | 12 | public extension View { 13 | /** 14 | Marks a SwiftUI View to be masked in PostHog session replay recordings. 15 | 16 | Because of the nature of how we intercept SwiftUI view hierarchy (and how it maps to UIKit), 17 | we can't always be 100% confident that a view should be masked and may accidentally mark a 18 | sensitive view as non-sensitive instead. 19 | 20 | Use this modifier to explicitly mask sensitive views in session replay recordings. 21 | 22 | For example: 23 | ```swift 24 | // This view will be masked in recordings 25 | SensitiveDataView() 26 | .postHogMask() 27 | 28 | // Conditionally mask based on a flag 29 | SensitiveDataView() 30 | .postHogMask(shouldMask) 31 | ``` 32 | 33 | - Parameter isEnabled: Whether masking should be enabled. Defaults to true. 34 | - Returns: A modified view that will be masked in session replay recordings when enabled 35 | */ 36 | func postHogMask(_ isEnabled: Bool = true) -> some View { 37 | modifier( 38 | PostHogTagViewModifier { uiViews in 39 | uiViews.forEach { $0.postHogNoCapture = isEnabled } 40 | } onRemove: { uiViews in 41 | uiViews.forEach { $0.postHogNoCapture = false } 42 | } 43 | ) 44 | } 45 | } 46 | 47 | extension UIView { 48 | var postHogNoCapture: Bool { 49 | get { objc_getAssociatedObject(self, &AssociatedKeys.phNoCapture) as? Bool ?? false } 50 | set { objc_setAssociatedObject(self, &AssociatedKeys.phNoCapture, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } 51 | } 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /PostHog/SwiftUI/PostHogNoMaskViewModifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogNoMaskViewModifier.swift 3 | // PostHog 4 | // 5 | // Created by Yiannis Josephides on 09/10/2024. 6 | // 7 | 8 | #if os(iOS) && canImport(SwiftUI) 9 | 10 | import SwiftUI 11 | 12 | public extension View { 13 | /** 14 | Marks a SwiftUI View to be excluded from masking in PostHog session replay recordings. 15 | 16 | There are cases where PostHog SDK will unintentionally mask some SwiftUI views. 17 | 18 | Because of the nature of how we intercept SwiftUI view hierarchy (and how it maps to UIKit), 19 | we can't always be 100% confident that a view should be masked. For that reason, we prefer to 20 | take a proactive and prefer to mask views if we're not sure. 21 | 22 | Use this modifier to prevent views from being masked in session replay recordings. 23 | 24 | For example: 25 | ```swift 26 | // This view may be accidentally masked by PostHog SDK 27 | SomeSafeView() 28 | 29 | // This custom view (and all its subviews) will not be masked in recordings 30 | SomeSafeView() 31 | .postHogNoMask() 32 | ``` 33 | 34 | - Returns: A modified view that will not be masked in session replay recordings 35 | */ 36 | func postHogNoMask() -> some View { 37 | modifier( 38 | PostHogTagViewModifier { uiViews in 39 | uiViews.forEach { $0.postHogNoMask = true } 40 | } onRemove: { uiViews in 41 | uiViews.forEach { $0.postHogNoMask = false } 42 | } 43 | ) 44 | } 45 | } 46 | 47 | extension UIView { 48 | var postHogNoMask: Bool { 49 | get { objc_getAssociatedObject(self, &AssociatedKeys.phNoMask) as? Bool ?? false } 50 | set { objc_setAssociatedObject(self, &AssociatedKeys.phNoMask, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } 51 | } 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /PostHog/SwiftUI/PostHogSwiftUIViewModifiers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogSwiftUIViewModifiers.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 05.09.24. 6 | // 7 | 8 | #if canImport(SwiftUI) 9 | import Foundation 10 | import SwiftUI 11 | 12 | public extension View { 13 | /** 14 | Marks a SwiftUI View to be tracked as a $screen event in PostHog when onAppear is called. 15 | 16 | - Parameters: 17 | - screenName: The name of the screen. Defaults to the type of the view. 18 | - properties: Additional properties to be tracked with the screen. 19 | - Returns: A modified view that will be tracked as a screen in PostHog. 20 | */ 21 | func postHogScreenView(_ screenName: String? = nil, 22 | _ properties: [String: Any]? = nil) -> some View 23 | { 24 | let viewEventName = screenName ?? "\(type(of: self))" 25 | return modifier(PostHogSwiftUIViewModifier(viewEventName: viewEventName, 26 | screenEvent: true, 27 | properties: properties)) 28 | } 29 | 30 | func postHogViewSeen(_ event: String, 31 | _ properties: [String: Any]? = nil) -> some View 32 | { 33 | modifier(PostHogSwiftUIViewModifier(viewEventName: event, 34 | screenEvent: false, 35 | properties: properties)) 36 | } 37 | } 38 | 39 | private struct PostHogSwiftUIViewModifier: ViewModifier { 40 | let viewEventName: String 41 | 42 | let screenEvent: Bool 43 | 44 | let properties: [String: Any]? 45 | 46 | func body(content: Content) -> some View { 47 | content.onAppear { 48 | if screenEvent { 49 | PostHogSDK.shared.screen(viewEventName, properties: properties) 50 | } else { 51 | PostHogSDK.shared.capture(viewEventName, properties: properties) 52 | } 53 | } 54 | } 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /PostHog/Utils/AssociatedKeys.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AssociatedKeys.swift 3 | // PostHog 4 | // 5 | // Created by Yiannis Josephides on 04/12/2024. 6 | // 7 | 8 | import Foundation 9 | 10 | enum AssociatedKeys { 11 | static var phForwardingDelegate: UInt8 = 0 12 | static var phNoCapture: UInt8 = 0 13 | static var phNoMask: UInt8 = 0 14 | static var phController: UInt8 = 0 15 | static var phView: UInt8 = 0 16 | static var phLabel: UInt8 = 0 17 | } 18 | -------------------------------------------------------------------------------- /PostHog/Utils/DateUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DateUtils.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 27.10.23. 6 | // 7 | 8 | import Foundation 9 | 10 | private func newDateFormatter() -> DateFormatter { 11 | let dateFormatter = DateFormatter() 12 | dateFormatter.locale = Locale(identifier: "en_US_POSIX") 13 | dateFormatter.timeZone = TimeZone(abbreviation: "UTC") 14 | 15 | dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" 16 | return dateFormatter 17 | } 18 | 19 | public func toISO8601String(_ date: Date) -> String { 20 | let dateFormatter = newDateFormatter() 21 | return dateFormatter.string(from: date) 22 | } 23 | 24 | public func toISO8601Date(_ date: String) -> Date? { 25 | let dateFormatter = newDateFormatter() 26 | return dateFormatter.date(from: date) 27 | } 28 | 29 | var now: () -> Date = { Date() } 30 | -------------------------------------------------------------------------------- /PostHog/Utils/DictUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DictUtils.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 27.10.23. 6 | // 7 | 8 | import Foundation 9 | 10 | public func sanitizeDictionary(_ dict: [String: Any]?) -> [String: Any]? { 11 | if dict == nil || dict!.isEmpty { 12 | return nil 13 | } 14 | 15 | var newDict = dict! 16 | 17 | for (key, value) in newDict where !isValidObject(value) { 18 | if value is URL { 19 | newDict[key] = (value as! URL).absoluteString 20 | continue 21 | } 22 | if value is Date { 23 | newDict[key] = ISO8601DateFormatter().string(from: (value as! Date)) 24 | continue 25 | } 26 | 27 | newDict.removeValue(forKey: key) 28 | hedgeLog("property: \(key) isn't serializable, dropping the item") 29 | } 30 | 31 | return newDict 32 | } 33 | 34 | private func isValidObject(_ object: Any) -> Bool { 35 | if object is String || object is Bool || object is any Numeric || object is NSNumber { 36 | return true 37 | } 38 | if object is [Any?] || object is [String: Any?] { 39 | return JSONSerialization.isValidJSONObject(object) 40 | } 41 | // workaround [object] since isValidJSONObject only accepts an Array or Dict 42 | return JSONSerialization.isValidJSONObject([object]) 43 | } 44 | -------------------------------------------------------------------------------- /PostHog/Utils/Errors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Errors.swift 3 | // PostHog 4 | // 5 | // Created by Ben White on 21.03.23. 6 | // 7 | 8 | import Foundation 9 | 10 | struct InternalPostHogError: Error, CustomStringConvertible { 11 | let description: String 12 | 13 | init(description: String, fileID: StaticString = #fileID, line: UInt = #line) { 14 | self.description = "\(description) (\(fileID):\(line))" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PostHog/Utils/FileUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FileUtils.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 30.10.23. 6 | // 7 | 8 | import Foundation 9 | 10 | public func deleteSafely(_ file: URL) { 11 | if FileManager.default.fileExists(atPath: file.path) { 12 | do { 13 | try FileManager.default.removeItem(at: file) 14 | } catch { 15 | hedgeLog("Error trying to delete file \(file.path) \(error)") 16 | } 17 | } 18 | } 19 | 20 | /// Check if provided directory exists 21 | func directoryExists(_ directory: URL) -> Bool { 22 | var isDirectory: ObjCBool = false 23 | return FileManager.default.fileExists(atPath: directory.path, isDirectory: &isDirectory) && isDirectory.boolValue 24 | } 25 | 26 | func createDirectoryAtURLIfNeeded(url: URL) { 27 | if FileManager.default.fileExists(atPath: url.path) { return } 28 | do { 29 | try FileManager.default.createDirectory(atPath: url.path, withIntermediateDirectories: true) 30 | } catch { 31 | hedgeLog("Error creating storage directory: \(error)") 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /PostHog/Utils/Hedgelog.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Hedgelog.swift 3 | // PostHog 4 | // 5 | // Created by Ben White on 07.02.23. 6 | // 7 | 8 | import Foundation 9 | 10 | var hedgeLogEnabled = false 11 | 12 | func toggleHedgeLog(_ enabled: Bool) { 13 | hedgeLogEnabled = enabled 14 | } 15 | 16 | // Meant for internally logging PostHog related things 17 | func hedgeLog(_ message: String) { 18 | if !hedgeLogEnabled { return } 19 | print("[PostHog] \(message)") 20 | } 21 | -------------------------------------------------------------------------------- /PostHog/Utils/ReadWriteLock.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. 3 | * This product includes software developed at Datadog (https://www.datadoghq.com/). 4 | * Copyright 2019-Present Datadog, Inc. 5 | */ 6 | 7 | import Foundation 8 | 9 | /// A property wrapper using a fair, POSIX conforming reader-writer lock for atomic 10 | /// access to the value. It is optimised for concurrent reads and exclusive writes. 11 | /// 12 | /// The wrapper is a class to prevent copying the lock, it creates and initilaizes a `pthread_rwlock_t`. 13 | /// An additional method `mutate` allow to safely mutate the value in-place (to read it 14 | /// and write it while obtaining the lock only once). 15 | @propertyWrapper 16 | public final class ReadWriteLock { 17 | /// The wrapped value. 18 | private var value: Value 19 | 20 | /// The lock object. 21 | private var rwlock = pthread_rwlock_t() 22 | 23 | public init(wrappedValue value: Value) { 24 | pthread_rwlock_init(&rwlock, nil) 25 | self.value = value 26 | } 27 | 28 | deinit { 29 | pthread_rwlock_destroy(&rwlock) 30 | } 31 | 32 | /// The wrapped value. 33 | /// 34 | /// The `get` will acquire the lock for reading while the `set` will acquire for 35 | /// writing. 36 | public var wrappedValue: Value { 37 | get { 38 | pthread_rwlock_rdlock(&rwlock) 39 | defer { pthread_rwlock_unlock(&rwlock) } 40 | return value 41 | } 42 | set { 43 | pthread_rwlock_wrlock(&rwlock) 44 | value = newValue 45 | pthread_rwlock_unlock(&rwlock) 46 | } 47 | } 48 | 49 | /// Provides a non-escaping closure for mutation. 50 | /// The lock will be acquired once for writing before invoking the closure. 51 | /// 52 | /// - Parameter closure: The closure with the mutable value. 53 | @discardableResult 54 | public func mutate(_ closure: (inout Value) -> T) -> T { 55 | pthread_rwlock_wrlock(&rwlock) 56 | defer { 57 | pthread_rwlock_unlock(&rwlock) 58 | } 59 | return closure(&value) 60 | } 61 | } 62 | 63 | func synchronized(_ lock: Any, closure: () -> Void) { 64 | objc_sync_enter(lock) 65 | closure() 66 | objc_sync_exit(lock) 67 | } 68 | -------------------------------------------------------------------------------- /PostHog/Utils/UIApplication+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIApplication+.swift 3 | // PostHog 4 | // 5 | // Created by Yiannis Josephides on 11/11/2024. 6 | // 7 | 8 | #if os(iOS) || os(tvOS) 9 | import UIKit 10 | 11 | extension UIApplication { 12 | static func getCurrentWindow(filterForegrounded: Bool = true) -> UIWindow? { 13 | let windowScenes = UIApplication.shared 14 | .connectedScenes 15 | .compactMap { $0 as? UIWindowScene } 16 | .filter { 17 | !filterForegrounded || $0.activationState == .foregroundActive 18 | } 19 | 20 | for scene in windowScenes { 21 | // attempt to retrieve directly from UIWindowScene 22 | if #available(iOS 15.0, tvOS 15.0, *) { 23 | if let keyWindow = scene.keyWindow { 24 | return keyWindow 25 | } 26 | } else { 27 | // check scene.windows.isKeyWindow 28 | for window in scene.windows where window.isKeyWindow { 29 | return window 30 | } 31 | } 32 | 33 | // check scene.delegate.window property 34 | let sceneDelegate = scene.delegate as? UIWindowSceneDelegate 35 | if let target = sceneDelegate, let window = target.window { 36 | return window 37 | } 38 | } 39 | 40 | return nil 41 | } 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /PostHog/Utils/UIWindow+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIWindow+.swift 3 | // PostHog 4 | // 5 | // Created by Yiannis Josephides on 03/12/2024. 6 | // 7 | 8 | #if os(iOS) || os(tvOS) 9 | import Foundation 10 | import UIKit 11 | 12 | /** 13 | Known keyboard window (private) types 14 | 15 | ## UIRemoteKeyboardWindow 16 | This is the window that manages the actual keyboard 17 | 18 | The following system view controllers were observed to be presented in a UIRemoteKeyboardWindow window 19 | - UIInputWindowController 20 | - UICompatibilityInputViewController 21 | - UISystemInputAssistantViewController 22 | - UIPredictionViewController 23 | - UISystemKeyboardDockController 24 | - TUIEmojiSearchInputViewController 25 | - STKPrewarmingViewController 26 | - STKStickerRemoteSearchViewController 27 | - _UIRemoteInputViewController 28 | - _UISceneHostingViewController 29 | - STKEmojiAndStickerCollectionViewController 30 | 31 | ## UITextEffectsWindow 32 | Hosts system components like the magnifying glass for text selection, predictive text suggestions, copy/paste menus, input accessory views etc. 33 | 34 | The following system view controllers were observed to be presented in a UITextEffectsWindow window 35 | - UIInputWindowController 36 | - UICompatibilityInputViewController 37 | 38 | These view controllers should not appear in a $screen event. If they do, then it means that they are presented in a UIWindow not listed below 39 | */ 40 | private let knownKeyboardWindowTypes: [String] = [ 41 | "UIRemoteKeyboardWindow", 42 | "UITextEffectsWindow", 43 | ] 44 | 45 | extension UIWindow { 46 | var isKeyboardWindow: Bool { 47 | knownKeyboardWindowTypes.contains(String(describing: type(of: self))) 48 | } 49 | } 50 | #endif 51 | -------------------------------------------------------------------------------- /PostHog/Utils/UUIDUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UUIDUtils.swift 3 | // PostHog 4 | // 5 | // Created by Manoel Aranda Neto on 17.06.24. 6 | // 7 | 8 | // Inspired and adapted from https://github.com/nthState/UUIDV7/blob/main/Sources/UUIDV7/UUIDV7.swift 9 | // but using SecRandomCopyBytes 10 | 11 | import Foundation 12 | 13 | extension UUID { 14 | static func v7() -> Self { 15 | TimeBasedEpochGenerator.shared.v7() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PostHogExample/Api.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Api.swift 3 | // PostHogExample 4 | // 5 | // Created by Ben White on 06.02.23. 6 | // 7 | 8 | import Foundation 9 | import OSLog 10 | 11 | struct PostHogBeerInfo: Codable, Identifiable { 12 | let id: Int 13 | var name: String 14 | var first_brewed: String 15 | } 16 | 17 | class Api: ObservableObject { 18 | @Published var beers = [PostHogBeerInfo]() 19 | 20 | var logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "main") 21 | 22 | func listBeers(completion _: @escaping ([PostHogBeerInfo]) -> Void) { 23 | // guard let url = URL(string: "https://api.punkapi.com/v2/beers") else { 24 | // return 25 | // } 26 | // 27 | // logger.info("Requesting beers list...") 28 | // URLSession.shared.dataTask(with: url) { _, _, _ in 29 | // let beers = try! JSONDecoder().decode([PostHogBeerInfo].self, from: data!) 30 | // 31 | // DispatchQueue.main.async { 32 | // completion(beers) 33 | // } 34 | // }.resume() 35 | } 36 | 37 | func failingRequest() -> URLSessionDataTask? { 38 | guard let url = URL(string: "https://api.github.com/user") else { 39 | return nil 40 | } 41 | 42 | logger.info("Requesting protected endpoint...") 43 | let task = URLSession.shared.dataTask(with: url) { data, _, _ in 44 | if data == nil { 45 | return 46 | } 47 | print("Response", String(decoding: data!, as: UTF8.self)) 48 | } 49 | 50 | task.resume() 51 | 52 | return task 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /PostHogExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PostHogExample 4 | // 5 | // Created by Ben White on 10.01.23. 6 | // 7 | 8 | import Foundation 9 | import PostHog 10 | import UIKit 11 | 12 | class AppDelegate: NSObject, UIApplicationDelegate { 13 | func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { 14 | let config = PostHogConfig( 15 | apiKey: "phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" 16 | ) 17 | // the ScreenViews for SwiftUI does not work, the names are not useful 18 | config.captureScreenViews = false 19 | config.captureApplicationLifecycleEvents = false 20 | // config.flushAt = 1 21 | // config.flushIntervalSeconds = 30 22 | config.debug = true 23 | config.sendFeatureFlagEvent = false 24 | config.sessionReplay = true 25 | config.sessionReplayConfig.screenshotMode = true 26 | config.sessionReplayConfig.maskAllTextInputs = true 27 | config.sessionReplayConfig.maskAllImages = true 28 | 29 | PostHogSDK.shared.setup(config) 30 | // PostHogSDK.shared.debug() 31 | // PostHogSDK.shared.capture("App started!") 32 | // PostHogSDK.shared.reset() 33 | 34 | // PostHogSDK.shared.identify("Manoel") 35 | 36 | let defaultCenter = NotificationCenter.default 37 | 38 | #if os(iOS) || os(tvOS) 39 | defaultCenter.addObserver(self, 40 | selector: #selector(receiveFeatureFlags), 41 | name: PostHogSDK.didReceiveFeatureFlags, 42 | object: nil) 43 | #endif 44 | 45 | return true 46 | } 47 | 48 | @objc func receiveFeatureFlags() { 49 | print("user receiveFeatureFlags callback") 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /PostHogExample/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PostHogExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExample/Assets.xcassets/max_static.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "max_static.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /PostHogExample/Assets.xcassets/max_static.imageset/max_static.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExample/Assets.xcassets/max_static.imageset/max_static.png -------------------------------------------------------------------------------- /PostHogExample/PostHogExample.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PostHogExample/PostHogExampleApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogExampleApp.swift 3 | // PostHogExample 4 | // 5 | // Created by Ben White on 10.01.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct PostHogExampleApp: App { 12 | @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate 13 | 14 | var body: some Scene { 15 | WindowGroup { 16 | ContentView() 17 | .postHogScreenView() // will infer the class name (ContentView) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /PostHogExample/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExample/Views/UIViewExample.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewExample.swift 3 | // PostHogExample 4 | // 5 | // Created by Ben White on 17.03.23. 6 | // 7 | 8 | import Foundation 9 | import SwiftUI 10 | import UIKit 11 | 12 | class ExampleUIView: UIView { 13 | private var label: UILabel = { 14 | let label = UILabel() 15 | label.translatesAutoresizingMaskIntoConstraints = false 16 | label.font = UIFont.preferredFont(forTextStyle: .title1) 17 | label.text = "Sensitive information!" 18 | label.textAlignment = .center 19 | 20 | return label 21 | }() 22 | 23 | init() { 24 | super.init(frame: .zero) 25 | backgroundColor = .systemPink 26 | accessibilityIdentifier = "ph-no-capture" 27 | 28 | addSubview(label) 29 | NSLayoutConstraint.activate([ 30 | label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), 31 | label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16), 32 | label.topAnchor.constraint(equalTo: topAnchor, constant: 20), 33 | label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -20), 34 | ]) 35 | } 36 | 37 | @available(*, unavailable) 38 | required init?(coder _: NSCoder) { 39 | fatalError("init(coder:) has not been implemented") 40 | } 41 | } 42 | 43 | struct RepresentedExampleUIView: UIViewRepresentable { 44 | typealias UIViewType = ExampleUIView 45 | 46 | func makeUIView(context _: Context) -> ExampleUIView { 47 | let view = ExampleUIView() 48 | 49 | // Do some configurations here if needed. 50 | return view 51 | } 52 | 53 | func updateUIView(_: ExampleUIView, context _: Context) { 54 | // Updates the state of the specified view controller with new information from SwiftUI. 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/LICENSE/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright © 2021 Apple Inc. 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. 8 | 9 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture.xcodeproj/.xcodesamplecode.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | The application-specific delegate class. 6 | */ 7 | 8 | import PostHog 9 | import UIKit 10 | 11 | @main 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 14 | let config = PostHogConfig( 15 | apiKey: "phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" 16 | ) 17 | config.debug = true 18 | 19 | config.captureElementInteractions = true 20 | config.captureApplicationLifecycleEvents = true 21 | config.sendFeatureFlagEvent = false 22 | 23 | config.sessionReplay = true 24 | config.captureScreenViews = true 25 | config.sessionReplayConfig.screenshotMode = true 26 | config.sessionReplayConfig.maskAllTextInputs = false 27 | config.sessionReplayConfig.maskAllImages = false 28 | 29 | PostHogSDK.shared.setup(config) 30 | 31 | PostHogSDK.shared.identify("Max Capture") 32 | 33 | return true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/Flowers_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Flowers_1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/Flowers_1.imageset/Flowers_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/Flowers_1.imageset/Flowers_1.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/Flowers_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Flowers_2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/Flowers_2.imageset/Flowers_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/Flowers_2.imageset/Flowers_2.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "stepper_and_segment_background_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "stepper_and_segment_background_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "stepper_and_segment_background_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background.imageset/stepper_and_segment_background_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background.imageset/stepper_and_segment_background_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background.imageset/stepper_and_segment_background_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background.imageset/stepper_and_segment_background_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background.imageset/stepper_and_segment_background_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background.imageset/stepper_and_segment_background_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_disabled.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "stepper_and_segment_background_disabled_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "stepper_and_segment_background_disabled_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "stepper_and_segment_background_disabled_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_disabled.imageset/stepper_and_segment_background_disabled_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_disabled.imageset/stepper_and_segment_background_disabled_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_disabled.imageset/stepper_and_segment_background_disabled_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_disabled.imageset/stepper_and_segment_background_disabled_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_disabled.imageset/stepper_and_segment_background_disabled_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_disabled.imageset/stepper_and_segment_background_disabled_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_highlighted.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "stepper_and_segment_background_highlighted_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "stepper_and_segment_background_highlighted_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "stepper_and_segment_background_highlighted_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_highlighted.imageset/stepper_and_segment_background_highlighted_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_highlighted.imageset/stepper_and_segment_background_highlighted_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_highlighted.imageset/stepper_and_segment_background_highlighted_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_highlighted.imageset/stepper_and_segment_background_highlighted_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_highlighted.imageset/stepper_and_segment_background_highlighted_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/background_highlighted.imageset/stepper_and_segment_background_highlighted_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/search_bar_background.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "search_bar_bg_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "search_bar_bg_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "search_bar_background_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/search_bar_background.imageset/search_bar_background_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/search_bar_background.imageset/search_bar_background_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/search_bar_background.imageset/search_bar_bg_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/search_bar_background.imageset/search_bar_bg_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/search_bar_background.imageset/search_bar_bg_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/search_bar_background.imageset/search_bar_bg_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_blue_track.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "slider_blue_track_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "slider_blue_track_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "slider_blue_track_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_blue_track.imageset/slider_blue_track_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_blue_track.imageset/slider_blue_track_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_blue_track.imageset/slider_blue_track_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_blue_track.imageset/slider_blue_track_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_blue_track.imageset/slider_blue_track_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_blue_track.imageset/slider_blue_track_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_green_track.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "slider_green_track_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "slider_green_track_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "slider_green_track_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_green_track.imageset/slider_green_track_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_green_track.imageset/slider_green_track_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_green_track.imageset/slider_green_track_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_green_track.imageset/slider_green_track_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_green_track.imageset/slider_green_track_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/slider_green_track.imageset/slider_green_track_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/stepper_and_segment_divider.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "stepper_and_segment_segment_divider_1x.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "stepper_and_segment_segment_divider_2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "stepper_and_segment_divider_3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/stepper_and_segment_divider.imageset/stepper_and_segment_divider_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/stepper_and_segment_divider.imageset/stepper_and_segment_divider_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/stepper_and_segment_divider.imageset/stepper_and_segment_segment_divider_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/stepper_and_segment_divider.imageset/stepper_and_segment_segment_divider_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/stepper_and_segment_divider.imageset/stepper_and_segment_segment_divider_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/stepper_and_segment_divider.imageset/stepper_and_segment_segment_divider_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_background.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "resizing" : { 5 | "mode" : "3-part-horizontal", 6 | "center" : { 7 | "mode" : "stretch", 8 | "width" : 0 9 | }, 10 | "cap-insets" : { 11 | "right" : 1, 12 | "left" : 1 13 | } 14 | }, 15 | "idiom" : "universal", 16 | "filename" : "text_field_background_1x.png", 17 | "scale" : "1x" 18 | }, 19 | { 20 | "resizing" : { 21 | "mode" : "3-part-horizontal", 22 | "center" : { 23 | "mode" : "stretch", 24 | "width" : 0 25 | }, 26 | "cap-insets" : { 27 | "right" : 1, 28 | "left" : 1 29 | } 30 | }, 31 | "idiom" : "universal", 32 | "filename" : "text_field_background_2x.png", 33 | "scale" : "2x" 34 | }, 35 | { 36 | "idiom" : "universal", 37 | "filename" : "text_field_background_3x.png", 38 | "scale" : "3x" 39 | } 40 | ], 41 | "info" : { 42 | "version" : 1, 43 | "author" : "xcode" 44 | } 45 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_background.imageset/text_field_background_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_background.imageset/text_field_background_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_background.imageset/text_field_background_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_background.imageset/text_field_background_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_background.imageset/text_field_background_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_background.imageset/text_field_background_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_purple_right_view.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "text_field_purple_right_view_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "text_field_purple_right_view_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "text_field_purple_right_view_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_purple_right_view.imageset/text_field_purple_right_view_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_purple_right_view.imageset/text_field_purple_right_view_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_purple_right_view.imageset/text_field_purple_right_view_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_purple_right_view.imageset/text_field_purple_right_view_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_purple_right_view.imageset/text_field_purple_right_view_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_field_purple_right_view.imageset/text_field_purple_right_view_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_view_attachment.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Sunset_5.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_view_attachment.imageset/Sunset_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_view_attachment.imageset/Sunset_5.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/text_view_background.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | }, 6 | "colors" : [ 7 | { 8 | "idiom" : "universal", 9 | "color" : { 10 | "color-space" : "srgb", 11 | "components" : { 12 | "red" : "1.000", 13 | "alpha" : "1.000", 14 | "blue" : "1.000", 15 | "green" : "1.000" 16 | } 17 | } 18 | }, 19 | { 20 | "idiom" : "universal", 21 | "appearances" : [ 22 | { 23 | "appearance" : "luminosity", 24 | "value" : "light" 25 | } 26 | ], 27 | "color" : { 28 | "color-space" : "srgb", 29 | "components" : { 30 | "red" : "1.000", 31 | "alpha" : "1.000", 32 | "blue" : "1.000", 33 | "green" : "1.000" 34 | } 35 | } 36 | }, 37 | { 38 | "idiom" : "universal", 39 | "appearances" : [ 40 | { 41 | "appearance" : "luminosity", 42 | "value" : "dark" 43 | } 44 | ], 45 | "color" : { 46 | "color-space" : "srgb", 47 | "components" : { 48 | "red" : "0.000", 49 | "alpha" : "0.000", 50 | "blue" : "0.000", 51 | "green" : "0.000" 52 | } 53 | } 54 | }, 55 | { 56 | "idiom" : "ipad", 57 | "color" : { 58 | "color-space" : "srgb", 59 | "components" : { 60 | "red" : "1.000", 61 | "alpha" : "1.000", 62 | "blue" : "1.000", 63 | "green" : "1.000" 64 | } 65 | } 66 | } 67 | ] 68 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/tinted_segmented_control.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | }, 6 | "colors" : [ 7 | { 8 | "idiom" : "universal", 9 | "color" : { 10 | "color-space" : "srgb", 11 | "components" : { 12 | "red" : "0.031", 13 | "alpha" : "1.000", 14 | "blue" : "0.500", 15 | "green" : "0.702" 16 | } 17 | } 18 | }, 19 | { 20 | "idiom" : "universal", 21 | "appearances" : [ 22 | { 23 | "appearance" : "luminosity", 24 | "value" : "light" 25 | } 26 | ], 27 | "color" : { 28 | "color-space" : "srgb", 29 | "components" : { 30 | "red" : "0.031", 31 | "alpha" : "1.000", 32 | "blue" : "0.500", 33 | "green" : "0.702" 34 | } 35 | } 36 | }, 37 | { 38 | "idiom" : "universal", 39 | "appearances" : [ 40 | { 41 | "appearance" : "luminosity", 42 | "value" : "dark" 43 | } 44 | ], 45 | "color" : { 46 | "color-space" : "srgb", 47 | "components" : { 48 | "red" : "0.209", 49 | "alpha" : "1.000", 50 | "blue" : "0.500", 51 | "green" : "0.938" 52 | } 53 | } 54 | }, 55 | { 56 | "idiom" : "ipad", 57 | "color" : { 58 | "color-space" : "srgb", 59 | "components" : { 60 | "red" : "0.031", 61 | "alpha" : "1.000", 62 | "blue" : "0.500", 63 | "green" : "0.702" 64 | } 65 | } 66 | } 67 | ] 68 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/tinted_stepper_control.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | }, 6 | "colors" : [ 7 | { 8 | "idiom" : "universal", 9 | "color" : { 10 | "color-space" : "srgb", 11 | "components" : { 12 | "red" : "0.031", 13 | "alpha" : "1.000", 14 | "blue" : "0.500", 15 | "green" : "0.702" 16 | } 17 | } 18 | }, 19 | { 20 | "idiom" : "universal", 21 | "appearances" : [ 22 | { 23 | "appearance" : "luminosity", 24 | "value" : "light" 25 | } 26 | ], 27 | "color" : { 28 | "color-space" : "srgb", 29 | "components" : { 30 | "red" : "0.031", 31 | "alpha" : "1.000", 32 | "blue" : "0.500", 33 | "green" : "0.702" 34 | } 35 | } 36 | }, 37 | { 38 | "idiom" : "universal", 39 | "appearances" : [ 40 | { 41 | "appearance" : "luminosity", 42 | "value" : "dark" 43 | } 44 | ], 45 | "color" : { 46 | "color-space" : "srgb", 47 | "components" : { 48 | "red" : "0.209", 49 | "alpha" : "1.000", 50 | "blue" : "0.500", 51 | "green" : "0.938" 52 | } 53 | } 54 | }, 55 | { 56 | "idiom" : "ipad", 57 | "color" : { 58 | "color-space" : "srgb", 59 | "components" : { 60 | "red" : "0.031", 61 | "alpha" : "1.000", 62 | "blue" : "0.500", 63 | "green" : "0.702" 64 | } 65 | } 66 | } 67 | ] 68 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/toolbar_background.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "toolbar_background_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "toolbar_background_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "toolbar_background_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/toolbar_background.imageset/toolbar_background_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/toolbar_background.imageset/toolbar_background_1x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/toolbar_background.imageset/toolbar_background_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/toolbar_background.imageset/toolbar_background_2x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/toolbar_background.imageset/toolbar_background_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogExampleAutocapture/PostHogExampleAutocapture/Assets.xcassets/toolbar_background.imageset/toolbar_background_3x.png -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Base.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf2617 2 | \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} 3 | {\colortbl;\red255\green255\blue255;\red0\green0\blue0;} 4 | {\*\expandedcolortbl;;\cssrgb\c0\c0\c0\cname textColor;} 5 | \vieww9000\viewh8400\viewkind0 6 | \pard\tx960\tx1920\tx2880\tx3840\tx4800\tx5760\tx6720\tx7680\tx8640\tx9600\qc\partightenfactor0 7 | 8 | \f0\fs20 \cf2 Demonstrates how to use {\field{\*\fldinst{HYPERLINK "https://developer.apple.com/documentation/uikit"}}{\fldrslt UIKit}}\ 9 | views, controls and pickers.\ 10 | } -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Base.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | Localized versions of Info.plist keys. 6 | */ 7 | 8 | CFBundleGetInfoString = "v16.0, Copyright 2008-2021, Apple Inc."; 9 | NSHumanReadableCopyright = "Copyright © 2008-2021, Apple Inc."; 10 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/Base.lproj/content.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WKWebView 5 | 10 | 11 | 12 |
13 |

This is HTML content inside a WKWebView.

14 | For more information refer to developer.apple.com 15 | 16 | 17 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/BaseTableViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | A base class used for all UITableViewControllers in this sample app. 6 | */ 7 | 8 | import UIKit 9 | 10 | class BaseTableViewController: UITableViewController { 11 | // List of table view cell test cases. 12 | var testCells = [CaseElement]() 13 | 14 | func centeredHeaderView(_ title: String) -> UITableViewHeaderFooterView { 15 | // Set the header title and make it centered. 16 | let headerView = UITableViewHeaderFooterView() 17 | var content = UIListContentConfiguration.groupedHeader() 18 | content.text = title 19 | content.textProperties.alignment = .center 20 | headerView.contentConfiguration = content 21 | return headerView 22 | } 23 | 24 | // MARK: - UITableViewDataSource 25 | 26 | override func tableView(_: UITableView, viewForHeaderInSection section: Int) -> UIView? { 27 | centeredHeaderView(testCells[section].title) 28 | } 29 | 30 | override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? { 31 | testCells[section].title 32 | } 33 | 34 | override func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int { 35 | 1 36 | } 37 | 38 | override func numberOfSections(in _: UITableView) -> Int { 39 | testCells.count 40 | } 41 | 42 | override func tableView(_ tableView: UITableView, 43 | cellForRowAt indexPath: IndexPath) -> UITableViewCell 44 | { 45 | let cellTest = testCells[indexPath.section] 46 | let cell = tableView.dequeueReusableCell(withIdentifier: cellTest.cellID, for: indexPath) 47 | if let view = cellTest.targetView(cell) { 48 | cellTest.configHandler(view) 49 | } 50 | return cell 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/CaseElement.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | Test case element that serves our UITableViewCells. 6 | */ 7 | 8 | import UIKit 9 | 10 | struct CaseElement { 11 | var title: String // Visual title of the cell (table section header title) 12 | var cellID: String // Table view cell's identifier for searching for the cell within the nib file. 13 | 14 | typealias ConfigurationClosure = (UIView) -> Void 15 | var configHandler: ConfigurationClosure // Configuration handler for setting up the cell's subview. 16 | 17 | init(title: String, cellID: String, configHandler: @escaping (V) -> Void) { 18 | self.title = title 19 | self.cellID = cellID 20 | self.configHandler = { view in 21 | guard let view = view as? V else { fatalError("Impossible") } 22 | configHandler(view) 23 | } 24 | } 25 | 26 | func targetView(_ cell: UITableViewCell?) -> UIView? { 27 | cell != nil ? cell!.contentView.subviews[0] : nil 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/CustomSearchBarViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | A view controller that demonstrates how to customize a `UISearchBar`. 6 | */ 7 | 8 | import UIKit 9 | 10 | class CustomSearchBarViewController: UIViewController { 11 | // MARK: - Properties 12 | 13 | @IBOutlet var searchBar: UISearchBar! 14 | 15 | // MARK: - View Life Cycle 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | configureSearchBar() 21 | } 22 | 23 | // MARK: - Configuration 24 | 25 | func configureSearchBar() { 26 | searchBar.showsCancelButton = true 27 | searchBar.showsBookmarkButton = true 28 | 29 | searchBar.tintColor = UIColor.systemPurple 30 | 31 | searchBar.backgroundImage = UIImage(named: "search_bar_background") 32 | 33 | // Set the bookmark image for both normal and highlighted states. 34 | let bookImage = UIImage(systemName: "bookmark") 35 | searchBar.setImage(bookImage, for: .bookmark, state: .normal) 36 | 37 | let bookFillImage = UIImage(systemName: "bookmark.fill") 38 | searchBar.setImage(bookFillImage, for: .bookmark, state: .highlighted) 39 | } 40 | } 41 | 42 | // MARK: - UISearchBarDelegate 43 | 44 | extension CustomSearchBarViewController: UISearchBarDelegate { 45 | func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 46 | Swift.debugPrint("The custom search bar keyboard \"Search\" button was tapped.") 47 | 48 | searchBar.resignFirstResponder() 49 | } 50 | 51 | func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { 52 | Swift.debugPrint("The custom search bar \"Cancel\" button was tapped.") 53 | 54 | searchBar.resignFirstResponder() 55 | } 56 | 57 | func searchBarBookmarkButtonClicked(_: UISearchBar) { 58 | Swift.debugPrint("The custom \"bookmark button\" inside the search bar was tapped.") 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/DefaultPageControlViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | A view controller that demonstrates how to use `UIPageControl`. 6 | */ 7 | 8 | import UIKit 9 | 10 | class PageControlViewController: UIViewController { 11 | // MARK: - Properties 12 | 13 | @IBOutlet var pageControl: UIPageControl! 14 | 15 | @IBOutlet var colorView: UIView! 16 | 17 | // Colors that correspond to the selected page. Used as the background color for `colorView`. 18 | let colors = [ 19 | UIColor.black, 20 | UIColor.systemGray, 21 | UIColor.systemRed, 22 | UIColor.systemGreen, 23 | UIColor.systemBlue, 24 | UIColor.systemPink, 25 | UIColor.systemYellow, 26 | UIColor.systemIndigo, 27 | UIColor.systemOrange, 28 | UIColor.systemPurple, 29 | ] 30 | 31 | // MARK: - View Life Cycle 32 | 33 | override func viewDidLoad() { 34 | super.viewDidLoad() 35 | 36 | configurePageControl() 37 | pageControlValueDidChange() 38 | } 39 | 40 | // MARK: - Configuration 41 | 42 | func configurePageControl() { 43 | // The total number of available pages is based on the number of available colors. 44 | pageControl.numberOfPages = colors.count 45 | pageControl.currentPage = 2 46 | 47 | pageControl.pageIndicatorTintColor = UIColor.systemGreen 48 | pageControl.currentPageIndicatorTintColor = UIColor.systemPurple 49 | 50 | pageControl.addTarget(self, action: #selector(PageControlViewController.pageControlValueDidChange), for: .valueChanged) 51 | } 52 | 53 | // MARK: - Actions 54 | 55 | @objc 56 | func pageControlValueDidChange() { 57 | // Note: gesture swiping between pages is provided by `UIPageViewController` and not `UIPageControl`. 58 | Swift.debugPrint("The page control changed its current page to \(pageControl.currentPage).") 59 | 60 | colorView.backgroundColor = colors[pageControl.currentPage] 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/DefaultSearchBarViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | A view controller that demonstrates how to use a default `UISearchBar`. 6 | */ 7 | 8 | import UIKit 9 | 10 | class DefaultSearchBarViewController: UIViewController { 11 | // MARK: - Properties 12 | 13 | @IBOutlet var searchBar: UISearchBar! 14 | 15 | // MARK: - View Life Cycle 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | configureSearchBar() 21 | } 22 | 23 | // MARK: - Configuration 24 | 25 | func configureSearchBar() { 26 | searchBar.showsCancelButton = true 27 | searchBar.showsScopeBar = true 28 | 29 | searchBar.scopeButtonTitles = [ 30 | NSLocalizedString("Scope One", comment: ""), 31 | NSLocalizedString("Scope Two", comment: ""), 32 | ] 33 | } 34 | } 35 | 36 | // MARK: - UISearchBarDelegate 37 | 38 | extension DefaultSearchBarViewController: UISearchBarDelegate { 39 | func searchBar(_: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { 40 | Swift.debugPrint("The default search selected scope button index changed to \(selectedScope).") 41 | } 42 | 43 | func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 44 | Swift.debugPrint("The default search bar keyboard search button was tapped: \(String(describing: searchBar.text)).") 45 | 46 | searchBar.resignFirstResponder() 47 | } 48 | 49 | func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { 50 | Swift.debugPrint("The default search bar cancel button was tapped.") 51 | 52 | searchBar.resignFirstResponder() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/DefaultToolbarViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | A view controller that demonstrates how to use a default `UIToolbar`. 6 | */ 7 | 8 | import UIKit 9 | 10 | class DefaultToolbarViewController: UIViewController { 11 | // MARK: - Properties 12 | 13 | @IBOutlet var toolbar: UIToolbar! 14 | 15 | // MARK: - View Life Cycle 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | 20 | let toolbarButtonItems = [ 21 | trashBarButtonItem, 22 | flexibleSpaceBarButtonItem, 23 | customTitleBarButtonItem, 24 | ] 25 | toolbar.setItems(toolbarButtonItems, animated: true) 26 | } 27 | 28 | // MARK: - UIBarButtonItem Creation and Configuration 29 | 30 | var trashBarButtonItem: UIBarButtonItem { 31 | UIBarButtonItem(barButtonSystemItem: .trash, 32 | target: self, 33 | action: #selector(DefaultToolbarViewController.barButtonItemClicked(_:))) 34 | } 35 | 36 | var flexibleSpaceBarButtonItem: UIBarButtonItem { 37 | UIBarButtonItem(barButtonSystemItem: .flexibleSpace, 38 | target: nil, 39 | action: nil) 40 | } 41 | 42 | func menuHandler(action: UIAction) { 43 | Swift.debugPrint("Menu Action '\(action.title)'") 44 | } 45 | 46 | var customTitleBarButtonItem: UIBarButtonItem { 47 | let buttonMenu = UIMenu(title: "", 48 | children: (1 ... 5).map { 49 | UIAction(title: "Option \($0)", handler: menuHandler) 50 | }) 51 | return UIBarButtonItem(image: UIImage(systemName: "list.number"), menu: buttonMenu) 52 | } 53 | 54 | // MARK: - Actions 55 | 56 | @objc 57 | func barButtonItemClicked(_ barButtonItem: UIBarButtonItem) { 58 | Swift.debugPrint("A bar button item on the default toolbar was clicked: \(barButtonItem).") 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/ImagePickerViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | A view controller that demonstrates how to use `UIFontPickerViewController`. 6 | */ 7 | 8 | import UIKit 9 | 10 | class ImagePickerViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { 11 | // MARK: - Properties 12 | 13 | var imagePicker: UIImagePickerController! 14 | @IBOutlet var imageView: UIImageView! 15 | 16 | // MARK: - View Life Cycle 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | 21 | configureImagePicker() 22 | } 23 | 24 | func configureImagePicker() { 25 | imagePicker = UIImagePickerController() 26 | imagePicker.delegate = self 27 | imagePicker.mediaTypes = ["public.image"] 28 | imagePicker.sourceType = .photoLibrary 29 | } 30 | 31 | @IBAction func presentImagePicker(_: AnyObject) { 32 | present(imagePicker, animated: true) 33 | } 34 | 35 | // MARK: - UIImagePickerControllerDelegate 36 | 37 | func imagePickerController(_ picker: UIImagePickerController, 38 | didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) 39 | { 40 | if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { 41 | imageView.image = image 42 | } 43 | picker.dismiss(animated: true, completion: nil) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/ImageViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | A view controller that demonstrates how to use `UIImageView`. 6 | */ 7 | 8 | import UIKit 9 | 10 | class ImageViewController: UIViewController { 11 | // MARK: - View Life Cycle 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | configureImageView() 17 | } 18 | 19 | // MARK: - Configuration 20 | 21 | func configureImageView() { 22 | // The root view of the view controller is set in Interface Builder and is an UIImageView. 23 | if let imageView = view as? UIImageView { 24 | // Fetch the images (each image is of the format Flowers_number). 25 | imageView.animationImages = (1 ... 2).map { UIImage(named: "Flowers_\($0)")! } 26 | 27 | // We want the image to be scaled to the correct aspect ratio within imageView's bounds. 28 | imageView.contentMode = .scaleAspectFit 29 | 30 | imageView.animationDuration = 5 31 | imageView.startAnimating() 32 | 33 | imageView.isAccessibilityElement = true 34 | imageView.accessibilityLabel = NSLocalizedString("Animated", comment: "") 35 | 36 | if #available(iOS 15, *) { 37 | // This case uses UIToolTipInteraction which is available on iOS 15 or later. 38 | let interaction = 39 | UIToolTipInteraction(defaultToolTip: NSLocalizedString("ImageToolTipTitle", comment: "")) 40 | imageView.addInteraction(interaction) 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/UIKitCatalog/Base.lproj/Localizable.stringsdict: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cart Items String 6 | 7 | NSStringLocalizedFormatKey 8 | %#@items@ 9 | items 10 | 11 | NSStringFormatSpecTypeKey 12 | NSStringPluralRuleType 13 | NSStringFormatValueTypeKey 14 | d 15 | one 16 | %d item 17 | other 18 | %d items 19 | 20 | 21 | 22 | Cart Tooltip String 23 | 24 | NSStringLocalizedFormatKey 25 | %#@items@ 26 | items 27 | 28 | NSStringFormatSpecTypeKey 29 | NSStringPluralRuleType 30 | NSStringFormatValueTypeKey 31 | d 32 | zero 33 | Cart is Empty 34 | one 35 | Cart has %d item 36 | other 37 | Cart has %d items 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /PostHogExampleAutocapture/PostHogExampleAutocapture/WebViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | See LICENSE folder for this sample’s licensing information. 3 | 4 | Abstract: 5 | A view controller that demonstrates how to use `WKWebView`. 6 | */ 7 | 8 | import UIKit 9 | import WebKit 10 | 11 | /** NOTE: 12 | If your app customizes, interacts with, or controls the display of web content, use the WKWebView class. 13 | If you want to view a website from anywhere on the Internet, use the SFSafariViewController class. 14 | */ 15 | 16 | class WebViewController: UIViewController { 17 | // MARK: - Properties 18 | 19 | @IBOutlet var webView: WKWebView! 20 | 21 | // MARK: - View Life Cycle 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | 26 | // So we can capture failures in "didFailProvisionalNavigation". 27 | webView.navigationDelegate = self 28 | loadAddressURL() 29 | } 30 | 31 | // MARK: - Loading 32 | 33 | func loadAddressURL() { 34 | // Set the content to local html in our app bundle. 35 | if let url = Bundle.main.url(forResource: "content", withExtension: "html") { 36 | webView.loadFileURL(url, allowingReadAccessTo: url) 37 | } 38 | } 39 | } 40 | 41 | // MARK: - WKNavigationDelegate 42 | 43 | extension WebViewController: WKNavigationDelegate { 44 | func webView(_ webView: WKWebView, didFailProvisionalNavigation _: WKNavigation!, withError error: Error) { 45 | let webKitError = error as NSError 46 | if webKitError.code == NSURLErrorNotConnectedToInternet { 47 | // Report the error inside the web view. 48 | let localizedErrorMessage = NSLocalizedString("An error occurred:", comment: "") 49 | 50 | let message = "\(localizedErrorMessage) \(error.localizedDescription)" 51 | let errorHTML = 52 | "
\(message)
" 53 | 54 | webView.loadHTMLString(errorHTML, baseURL: nil) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/ExternalSDK.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExternalSDK.swift 3 | // ExternalSDK 4 | // 5 | // Created by Yiannis Josephides on 24/01/2025. 6 | // 7 | 8 | import Foundation 9 | import PostHog 10 | 11 | public final class MyExternalSDK { 12 | public static let shared = MyExternalSDK() 13 | 14 | private init() { 15 | let config = PostHogConfig( 16 | apiKey: "phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" 17 | ) 18 | 19 | config.captureScreenViews = true 20 | config.captureApplicationLifecycleEvents = true 21 | config.debug = true 22 | config.sendFeatureFlagEvent = false 23 | config.sessionReplay = true 24 | config.sessionReplayConfig.maskAllImages = false 25 | config.sessionReplayConfig.maskAllTextInputs = false 26 | config.sessionReplayConfig.maskAllSandboxedViews = false 27 | 28 | PostHogSDK.shared.setup(config) 29 | } 30 | 31 | public func track(event: String) { 32 | PostHogSDK.shared.capture("An Event From ExternalSDK - \(event)") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/ExternalSDK/ExternalSDK.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExternalSDK.h 3 | // ExternalSDK 4 | // 5 | // Created by Yiannis Josephides on 23/01/2025. 6 | // 7 | 8 | #import 9 | 10 | //! Project version number for ExternalSDK. 11 | FOUNDATION_EXPORT double ExternalSDKVersionNumber; 12 | 13 | //! Project version string for TestBuildIssues. 14 | FOUNDATION_EXPORT const unsigned char ExternalSDKVersionString[]; 15 | 16 | // In this header, you should import all the public headers of your framework using statements like #import 17 | 18 | 19 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.10 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "ExternalSDK", 8 | platforms: [.iOS(.v15)], 9 | products: [ 10 | .library( 11 | name: "ExternalSDK", 12 | targets: ["ExternalSDK-iOS"] 13 | ), 14 | ], 15 | dependencies: [ 16 | .package(path: "../"), 17 | ], 18 | targets: [ 19 | .target( 20 | name: "ExternalSDK-iOS", 21 | dependencies: [ 22 | .product(name: "PostHog", package: "posthog-ios"), 23 | .target(name: "ExternalSDK"), 24 | ] 25 | ), 26 | .binaryTarget(name: "ExternalSDK", path: "./build/bin/ExternalSDK.xcframework"), 27 | ] 28 | ) 29 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/SDKClient/ExternalSDKClient/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/SDKClient/ExternalSDKClient/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | }, 30 | { 31 | "idiom" : "mac", 32 | "scale" : "1x", 33 | "size" : "16x16" 34 | }, 35 | { 36 | "idiom" : "mac", 37 | "scale" : "2x", 38 | "size" : "16x16" 39 | }, 40 | { 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "32x32" 44 | }, 45 | { 46 | "idiom" : "mac", 47 | "scale" : "2x", 48 | "size" : "32x32" 49 | }, 50 | { 51 | "idiom" : "mac", 52 | "scale" : "1x", 53 | "size" : "128x128" 54 | }, 55 | { 56 | "idiom" : "mac", 57 | "scale" : "2x", 58 | "size" : "128x128" 59 | }, 60 | { 61 | "idiom" : "mac", 62 | "scale" : "1x", 63 | "size" : "256x256" 64 | }, 65 | { 66 | "idiom" : "mac", 67 | "scale" : "2x", 68 | "size" : "256x256" 69 | }, 70 | { 71 | "idiom" : "mac", 72 | "scale" : "1x", 73 | "size" : "512x512" 74 | }, 75 | { 76 | "idiom" : "mac", 77 | "scale" : "2x", 78 | "size" : "512x512" 79 | } 80 | ], 81 | "info" : { 82 | "author" : "xcode", 83 | "version" : 1 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/SDKClient/ExternalSDKClient/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/SDKClient/ExternalSDKClient/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // TestBuildIssuesClient 4 | // 5 | // Created by Yiannis Josephides on 24/01/2025. 6 | // 7 | 8 | import ExternalSDK 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | var body: some View { 13 | VStack(spacing: 16) { 14 | Button("Track Event") { 15 | MyExternalSDK.shared.track(event: "test") 16 | } 17 | Image(systemName: "globe") 18 | .imageScale(.large) 19 | .foregroundStyle(.tint) 20 | Text("Hello, world!") 21 | } 22 | .padding() 23 | } 24 | } 25 | 26 | #Preview { 27 | ContentView() 28 | } 29 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/SDKClient/ExternalSDKClient/ExternalSDKClient.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/SDKClient/ExternalSDKClient/ExternalSDKClientApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExternalSDKClientApp.swift 3 | // TestBuildIssuesClient 4 | // 5 | // Created by Yiannis Josephides on 24/01/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct TestBuildIssuesClientApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/SDKClient/ExternalSDKClient/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/Sources/ExternalSDK-iOS/ExternalSDK-iOS.swift: -------------------------------------------------------------------------------- 1 | // wrapper 2 | -------------------------------------------------------------------------------- /PostHogExampleExternalSDK/build_xcframework.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the directory where the script is located 4 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | 6 | # Define output directories relative to script location 7 | OUTPUT_DIR="$SCRIPT_DIR/build" 8 | ARCHIVE_DIR="$OUTPUT_DIR/archives" 9 | PROJECT_PATH="$SCRIPT_DIR/PostHogExampleExternalSDK.xcodeproj" 10 | 11 | rm -rf "$OUTPUT_DIR" 12 | rm -rf "$ARCHIVE_DIR" 13 | mkdir -p "$OUTPUT_DIR" 14 | mkdir -p "$ARCHIVE_DIR" 15 | 16 | echo "Building for iOS devices..." 17 | if ! xcodebuild archive \ 18 | SKIP_INSTALL=NO \ 19 | BUILD_LIBRARY_FOR_DISTRIBUTION=YES \ 20 | ENABLE_MODULE_VERIFIER=YES \ 21 | -project "$PROJECT_PATH" \ 22 | -scheme ExternalSDK \ 23 | -configuration Release \ 24 | -destination "generic/platform=iOS" \ 25 | -archivePath "$ARCHIVE_DIR/ExternalSDK-iOS.xcarchive" | xcpretty; then 26 | echo "Error: Failed to build framework for iOS Device" 27 | fi 28 | 29 | echo "Building for iOS simulator..." 30 | if ! xcodebuild archive \ 31 | SKIP_INSTALL=NO \ 32 | BUILD_LIBRARY_FOR_DISTRIBUTION=YES \ 33 | ENABLE_MODULE_VERIFIER=YES \ 34 | -project "$PROJECT_PATH" \ 35 | -scheme ExternalSDK \ 36 | -configuration Release \ 37 | -destination "generic/platform=iOS Simulator" \ 38 | -archivePath "$ARCHIVE_DIR/ExternalSDK-iOS_Simulator.xcarchive" | xcpretty; then 39 | echo "Error: Failed to build framework for iOS Simulator" 40 | fi 41 | 42 | echo "Creating XCFramework..." 43 | if ! xcodebuild -create-xcframework \ 44 | -archive "$ARCHIVE_DIR/ExternalSDK-iOS.xcarchive" -framework ExternalSDK.framework \ 45 | -archive "$ARCHIVE_DIR/ExternalSDK-iOS_Simulator.xcarchive" -framework ExternalSDK.framework \ 46 | -output "$OUTPUT_DIR/bin/ExternalSDK.xcframework" | xcpretty; then 47 | echo "Error: Failed to create XCFramework" 48 | exit 1 49 | fi 50 | 51 | echo "XCFramework created at $OUTPUT_DIR/bin/ExternalSDK.xcframework" -------------------------------------------------------------------------------- /PostHogExampleMacOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import PostHog 3 | 4 | class AppDelegate: NSObject, NSApplicationDelegate { 5 | func applicationDidFinishLaunching(_: Notification) { 6 | let config = PostHogConfig( 7 | apiKey: "phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" 8 | ) 9 | config.debug = true 10 | 11 | PostHogSDK.shared.setup(config) 12 | // PostHogSDK.shared.capture("Event from MacOS example!") 13 | } 14 | 15 | func applicationWillTerminate(_: Notification) { 16 | // Insert code here to tear down your application 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PostHogExampleMacOS/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleMacOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "2x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "1x", 16 | "size" : "32x32" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "2x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "1x", 26 | "size" : "128x128" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "1x", 36 | "size" : "256x256" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "2x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "1x", 46 | "size" : "512x512" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "scale" : "2x", 51 | "size" : "512x512" 52 | } 53 | ], 54 | "info" : { 55 | "author" : "xcode", 56 | "version" : 1 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /PostHogExampleMacOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleMacOS/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // PostHogExampleMacOS 4 | // 5 | // Created by Manoel Aranda Neto on 10.11.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | VStack { 13 | Image(systemName: "globe") 14 | .imageScale(.large) 15 | .foregroundStyle(.tint) 16 | Text("Hello, world!") 17 | } 18 | .padding() 19 | } 20 | } 21 | 22 | #Preview { 23 | ContentView() 24 | } 25 | -------------------------------------------------------------------------------- /PostHogExampleMacOS/PostHogExampleMacOS.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /PostHogExampleMacOS/PostHogExampleMacOSApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogExampleMacOSApp.swift 3 | // PostHogExampleMacOS 4 | // 5 | // Created by Manoel Aranda Neto on 10.11.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct PostHogExampleMacOSApp: App { 12 | @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate 13 | 14 | var body: some Scene { 15 | WindowGroup { 16 | ContentView() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PostHogExampleMacOS/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleStoryboard/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PostHogExampleStoryboard 4 | // 5 | // Created by Manoel Aranda Neto on 21.03.24. 6 | // 7 | 8 | import PostHog 9 | import UIKit 10 | 11 | @main 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 14 | // Override point for customization after application launch. 15 | let config = PostHogConfig( 16 | apiKey: "phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" 17 | ) 18 | // the ScreenViews for SwiftUI does not work, the names are not useful 19 | config.captureScreenViews = false 20 | config.captureApplicationLifecycleEvents = false 21 | // config.flushAt = 1 22 | // config.flushIntervalSeconds = 30 23 | config.debug = true 24 | config.sendFeatureFlagEvent = false 25 | config.sessionReplay = true 26 | config.sessionReplayConfig.maskAllTextInputs = true 27 | config.sessionReplayConfig.screenshotMode = true 28 | config.sessionReplayConfig.maskAllImages = true 29 | config.sessionReplayConfig.captureNetworkTelemetry = true 30 | 31 | PostHogSDK.shared.setup(config) 32 | 33 | return true 34 | } 35 | 36 | // MARK: UISceneSession Lifecycle 37 | 38 | func application(_: UIApplication, 39 | configurationForConnecting connectingSceneSession: UISceneSession, 40 | options _: UIScene.ConnectionOptions) -> UISceneConfiguration 41 | { 42 | // Called when a new scene session is being created. 43 | // Use this method to select a configuration to create the new scene with. 44 | UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 45 | } 46 | 47 | func application(_: UIApplication, didDiscardSceneSessions _: Set) { 48 | // Called when the user discards a scene session. 49 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 50 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /PostHogExampleStoryboard/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleStoryboard/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PostHogExampleStoryboard/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleStoryboard/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /PostHogExampleStoryboard/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /PostHogExampleStoryboard/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationSceneManifest 6 | 7 | UIApplicationSupportsMultipleScenes 8 | 9 | UISceneConfigurations 10 | 11 | UIWindowSceneSessionRoleApplication 12 | 13 | 14 | UISceneConfigurationName 15 | Default Configuration 16 | UISceneDelegateClassName 17 | $(PRODUCT_MODULE_NAME).SceneDelegate 18 | UISceneStoryboardFile 19 | Main 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import PostHog 2 | import SwiftUI 3 | import UIKit 4 | 5 | class AppDelegate: UIResponder, UIApplicationDelegate { 6 | var window: UIWindow? 7 | 8 | func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 9 | let config = PostHogConfig( 10 | apiKey: "phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" 11 | ) 12 | config.debug = true 13 | 14 | PostHogSDK.shared.setup(config) 15 | PostHogSDK.shared.capture("Event from TvOS example!") 16 | 17 | return true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "layers" : [ 7 | { 8 | "filename" : "Front.imagestacklayer" 9 | }, 10 | { 11 | "filename" : "Middle.imagestacklayer" 12 | }, 13 | { 14 | "filename" : "Back.imagestacklayer" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "layers" : [ 7 | { 8 | "filename" : "Front.imagestacklayer" 9 | }, 10 | { 11 | "filename" : "Middle.imagestacklayer" 12 | }, 13 | { 14 | "filename" : "Back.imagestacklayer" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "filename" : "App Icon - App Store.imagestack", 5 | "idiom" : "tv", 6 | "role" : "primary-app-icon", 7 | "size" : "1280x768" 8 | }, 9 | { 10 | "filename" : "App Icon.imagestack", 11 | "idiom" : "tv", 12 | "role" : "primary-app-icon", 13 | "size" : "400x240" 14 | }, 15 | { 16 | "filename" : "Top Shelf Image Wide.imageset", 17 | "idiom" : "tv", 18 | "role" : "top-shelf-image-wide", 19 | "size" : "2320x720" 20 | }, 21 | { 22 | "filename" : "Top Shelf Image.imageset", 23 | "idiom" : "tv", 24 | "role" : "top-shelf-image", 25 | "size" : "1920x720" 26 | } 27 | ], 28 | "info" : { 29 | "author" : "xcode", 30 | "version" : 1 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "author" : "xcode", 14 | "version" : 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // PostHogExampleTvOS 4 | // 5 | // Created by Manoel Aranda Neto on 10.11.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | VStack { 13 | Image(systemName: "globe") 14 | .imageScale(.large) 15 | .foregroundStyle(.tint) 16 | Text("Hello, world!") 17 | } 18 | .padding() 19 | } 20 | } 21 | 22 | #Preview { 23 | ContentView() 24 | } 25 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/PostHogExampleTvOSApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogExampleTvOSApp.swift 3 | // PostHogExampleTvOS 4 | // 5 | // Created by Manoel Aranda Neto on 10.11.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct PostHogExampleTvOSApp: App { 12 | @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate 13 | 14 | var body: some Scene { 15 | WindowGroup { 16 | ContentView() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PostHogExampleTvOS/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleWatchOS/PostHogExampleWatchOS Watch App/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleWatchOS/PostHogExampleWatchOS Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "watchos", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PostHogExampleWatchOS/PostHogExampleWatchOS Watch App/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleWatchOS/PostHogExampleWatchOS Watch App/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // PostHogExampleWatchOS Watch App 4 | // 5 | // Created by Manoel Aranda Neto on 02.11.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | VStack { 13 | Image(systemName: "globe") 14 | .imageScale(.large) 15 | .foregroundStyle(.tint) 16 | Text("Hello, world!") 17 | } 18 | .padding() 19 | } 20 | } 21 | 22 | #Preview { 23 | ContentView() 24 | } 25 | -------------------------------------------------------------------------------- /PostHogExampleWatchOS/PostHogExampleWatchOS Watch App/PostHogExampleWatchOSApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogExampleWatchOSApp.swift 3 | // PostHogExampleWatchOS Watch App 4 | // 5 | // Created by Manoel Aranda Neto on 02.11.23. 6 | // 7 | 8 | import PostHog 9 | import SwiftUI 10 | 11 | @main 12 | struct PostHogExampleWatchOSApp: App { 13 | init() { 14 | // TODO: init on app delegate instead 15 | let config = PostHogConfig( 16 | apiKey: "phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" 17 | ) 18 | 19 | PostHogSDK.shared.setup(config) 20 | PostHogSDK.shared.debug() 21 | PostHogSDK.shared.capture("Event from WatchOS example!") 22 | } 23 | 24 | var body: some Scene { 25 | WindowGroup { 26 | ContentView() 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PostHogExampleWatchOS/PostHogExampleWatchOS Watch App/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '16.0' 2 | 3 | use_frameworks! 4 | 5 | target 'PostHogExampleWithPods' do 6 | pod 'PostHog', :path => '../' 7 | end 8 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/Podfile.static: -------------------------------------------------------------------------------- 1 | platform :ios, '16.0' 2 | 3 | target 'PostHogExampleWithPods' do 4 | pod 'PostHog', :path => '../' 5 | end 6 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/PostHogExampleWithPods/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PostHogExampleWithPods 4 | // 5 | // Created by Manoel Aranda Neto on 24.10.23. 6 | // 7 | 8 | import Foundation 9 | import PostHog 10 | import UIKit 11 | 12 | class AppDelegate: NSObject, UIApplicationDelegate { 13 | func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { 14 | let defaultCenter = NotificationCenter.default 15 | 16 | defaultCenter.addObserver(self, 17 | selector: #selector(receiveFeatureFlags), 18 | name: PostHogSDK.didReceiveFeatureFlags, 19 | object: nil) 20 | 21 | let config = PostHogConfig( 22 | apiKey: "phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" 23 | ) 24 | 25 | PostHogSDK.shared.setup(config) 26 | PostHogSDK.shared.debug() 27 | PostHogSDK.shared.capture("Event from CocoaPods example!") 28 | 29 | return true 30 | } 31 | 32 | @objc func receiveFeatureFlags() { 33 | print("receiveFeatureFlags") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/PostHogExampleWithPods/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/PostHogExampleWithPods/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/PostHogExampleWithPods/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/PostHogExampleWithPods/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // PostHogExampleWithPods 4 | // 5 | // Created by Manoel Aranda Neto on 24.10.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | VStack { 13 | Image(systemName: "globe") 14 | .imageScale(.large) 15 | .foregroundStyle(.tint) 16 | Text("Hello, world!") 17 | } 18 | .padding() 19 | } 20 | } 21 | 22 | #Preview { 23 | ContentView() 24 | } 25 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/PostHogExampleWithPods/PostHogExampleWithPodsApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogExampleWithPodsApp.swift 3 | // PostHogExampleWithPods 4 | // 5 | // Created by Manoel Aranda Neto on 24.10.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct PostHogExampleWithPodsApp: App { 12 | @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate 13 | 14 | var body: some Scene { 15 | WindowGroup { 16 | ContentView() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/PostHogExampleWithPods/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleWithPods/README.md: -------------------------------------------------------------------------------- 1 | # Example with CocoaPods 2 | 3 | This is an example of how to use the PostHog iOS SDK with CocoaPods. 4 | 5 | ## Installation 6 | 7 | 1. Install CocoaPods if you haven't already: 8 | 9 | 10 | 11 | ```bash 12 | sudo gem install cocoapods 13 | ``` 14 | 15 | ## Add a Podfile to the project 16 | 17 | 18 | 19 | ```text 20 | platform :ios, '16.0' 21 | 22 | use_frameworks! 23 | 24 | target '$your_project' do 25 | pod 'PostHog', '~> 3.0.0' 26 | end 27 | ``` 28 | 29 | Replace `$your_project` to your project name. 30 | 31 | ## Run `pod install` 32 | 33 | ```bash 34 | pod install 35 | ``` 36 | 37 | ## Open the project 38 | 39 | Always open the `*.xcworkspace` file, not the `*.xcodeproj` file. 40 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/PostHogExampleWithSPM.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/PostHogExampleWithSPM.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/PostHogExampleWithSPM/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // PostHogExampleWithPods 4 | // 5 | // Created by Manoel Aranda Neto on 24.10.23. 6 | // 7 | import Foundation 8 | import PostHog 9 | import UIKit 10 | 11 | class AppDelegate: NSObject, UIApplicationDelegate { 12 | func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { 13 | let defaultCenter = NotificationCenter.default 14 | 15 | defaultCenter.addObserver(self, 16 | selector: #selector(receiveFeatureFlags), 17 | name: PostHogSDK.didReceiveFeatureFlags, 18 | object: nil) 19 | 20 | let config = PostHogConfig( 21 | apiKey: "phc_QFbR1y41s5sxnNTZoyKG2NJo2RlsCIWkUfdpawgb40D" 22 | ) 23 | 24 | PostHogSDK.shared.setup(config) 25 | PostHogSDK.shared.debug() 26 | PostHogSDK.shared.capture("Event from SPM example!") 27 | 28 | return true 29 | } 30 | 31 | @objc func receiveFeatureFlags() { 32 | print("receiveFeatureFlags") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/PostHogExampleWithSPM/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/PostHogExampleWithSPM/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/PostHogExampleWithSPM/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/PostHogExampleWithSPM/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // PostHogExampleWithSPM 4 | // 5 | // Created by Manoel Aranda Neto on 24.10.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | VStack { 13 | Image(systemName: "globe") 14 | .imageScale(.large) 15 | .foregroundStyle(.tint) 16 | Text("Hello, world!") 17 | } 18 | .padding() 19 | } 20 | } 21 | 22 | #Preview { 23 | ContentView() 24 | } 25 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/PostHogExampleWithSPM/PostHogExampleWithSPMApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogExampleWithSPMApp.swift 3 | // PostHogExampleWithSPM 4 | // 5 | // Created by Manoel Aranda Neto on 24.10.23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct PostHogExampleWithSPMApp: App { 12 | @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate 13 | 14 | var body: some Scene { 15 | WindowGroup { 16 | ContentView() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/PostHogExampleWithSPM/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogExampleWithSPM/README.md: -------------------------------------------------------------------------------- 1 | # Example with SPM 2 | 3 | This is an example of how to use the PostHog iOS SDK with SPM. 4 | 5 | ## Installation 6 | 7 | 1. Install Xcode if you haven't already: 8 | 9 | Follow steps from the [Xcode docs](https://developer.apple.com/xcode/resources/). 10 | 11 | ## Add a SP dependency to the project via Xcode 12 | 13 | 1. Click on the project in the Project Navigator. 14 | 2. Select the project in the Project and Targets list. 15 | 3. Select the General tab. 16 | 4. Scroll down to the Frameworks and Libraries section. 17 | 5. Click the + button. 18 | 6. Click Add Other... 19 | 7. Click Add Package Dependency 20 | 8. Enter the URL of the PostHog SDK repo or the local path to the repo. 21 | 22 | ## Import the PostHog package 23 | 24 | ```swift 25 | import PostHog 26 | ``` 27 | 28 | And run the project. 29 | -------------------------------------------------------------------------------- /PostHogObjCExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PostHogObjCExample 4 | // 5 | // Created by Manoel Aranda Neto on 23.10.23. 6 | // 7 | 8 | #import 9 | 10 | @interface AppDelegate : UIResponder 11 | 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /PostHogObjCExample/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PostHogObjCExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /PostHogObjCExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PostHogObjCExample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /PostHogObjCExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /PostHogObjCExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationSceneManifest 6 | 7 | UIApplicationSupportsMultipleScenes 8 | 9 | UISceneConfigurations 10 | 11 | UIWindowSceneSessionRoleApplication 12 | 13 | 14 | UISceneConfigurationName 15 | Default Configuration 16 | UISceneDelegateClassName 17 | SceneDelegate 18 | UISceneStoryboardFile 19 | Main 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /PostHogObjCExample/SceneDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.h 3 | // PostHogObjCExample 4 | // 5 | // Created by Manoel Aranda Neto on 23.10.23. 6 | // 7 | 8 | #import 9 | 10 | @interface SceneDelegate : UIResponder 11 | 12 | @property (strong, nonatomic) UIWindow * window; 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /PostHogObjCExample/SceneDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.m 3 | // PostHogObjCExample 4 | // 5 | // Created by Manoel Aranda Neto on 23.10.23. 6 | // 7 | 8 | #import "SceneDelegate.h" 9 | 10 | @interface SceneDelegate () 11 | 12 | @end 13 | 14 | @implementation SceneDelegate 15 | 16 | 17 | - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | } 22 | 23 | 24 | - (void)sceneDidDisconnect:(UIScene *)scene { 25 | // Called as the scene is being released by the system. 26 | // This occurs shortly after the scene enters the background, or when its session is discarded. 27 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 28 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). 29 | } 30 | 31 | 32 | - (void)sceneDidBecomeActive:(UIScene *)scene { 33 | // Called when the scene has moved from an inactive state to an active state. 34 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 35 | } 36 | 37 | 38 | - (void)sceneWillResignActive:(UIScene *)scene { 39 | // Called when the scene will move from an active state to an inactive state. 40 | // This may occur due to temporary interruptions (ex. an incoming phone call). 41 | } 42 | 43 | 44 | - (void)sceneWillEnterForeground:(UIScene *)scene { 45 | // Called as the scene transitions from the background to the foreground. 46 | // Use this method to undo the changes made on entering the background. 47 | } 48 | 49 | 50 | - (void)sceneDidEnterBackground:(UIScene *)scene { 51 | // Called as the scene transitions from the foreground to the background. 52 | // Use this method to save data, release shared resources, and store enough scene-specific state information 53 | // to restore the scene back to its current state. 54 | } 55 | 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /PostHogObjCExample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // PostHogObjCExample 4 | // 5 | // Created by Manoel Aranda Neto on 23.10.23. 6 | // 7 | 8 | #import 9 | 10 | @interface ViewController : UIViewController 11 | 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /PostHogObjCExample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // PostHogObjCExample 4 | // 5 | // Created by Manoel Aranda Neto on 23.10.23. 6 | // 7 | 8 | #import "ViewController.h" 9 | 10 | @interface ViewController () 11 | 12 | @end 13 | 14 | @implementation ViewController 15 | 16 | - (void)viewDidLoad { 17 | [super viewDidLoad]; 18 | // Do any additional setup after loading the view. 19 | } 20 | 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /PostHogObjCExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PostHogObjCExample 4 | // 5 | // Created by Manoel Aranda Neto on 23.10.23. 6 | // 7 | 8 | #import 9 | #import "AppDelegate.h" 10 | 11 | int main(int argc, char * argv[]) { 12 | NSString * appDelegateClassName; 13 | @autoreleasepool { 14 | // Setup code that might create autoreleased objects goes here. 15 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 16 | } 17 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 18 | } 19 | -------------------------------------------------------------------------------- /PostHogTests/ExampleSanitizer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleSanitizer.swift 3 | // PostHogTests 4 | // 5 | // Created by Manoel Aranda Neto on 06.08.24. 6 | // 7 | 8 | import Foundation 9 | import PostHog 10 | 11 | class ExampleSanitizer: PostHogPropertiesSanitizer { 12 | public func sanitize(_ properties: [String: Any]) -> [String: Any] { 13 | var sanitizedProperties = properties 14 | // Perform sanitization 15 | // For example, removing keys with empty values 16 | for (key, value) in properties { 17 | if let stringValue = value as? String, stringValue.isEmpty { 18 | sanitizedProperties.removeValue(forKey: key) 19 | } 20 | } 21 | return sanitizedProperties 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /PostHogTests/PostHogConfigTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogConfigTest.swift 3 | // PostHogTests 4 | // 5 | // Created by Manoel Aranda Neto on 30.10.23. 6 | // 7 | 8 | import Foundation 9 | import Nimble 10 | @testable import PostHog 11 | import Quick 12 | 13 | class PostHogConfigTest: QuickSpec { 14 | override func spec() { 15 | it("init config with default values") { 16 | let config = PostHogConfig(apiKey: "123") 17 | 18 | expect(config.host) == URL(string: PostHogConfig.defaultHost) 19 | expect(config.flushAt) == 20 20 | expect(config.maxQueueSize) == 1000 21 | expect(config.maxBatchSize) == 50 22 | expect(config.flushIntervalSeconds) == 30 23 | expect(config.dataMode) == .any 24 | expect(config.sendFeatureFlagEvent) == true 25 | expect(config.preloadFeatureFlags) == true 26 | expect(config.captureApplicationLifecycleEvents) == true 27 | expect(config.captureScreenViews) == true 28 | expect(config.debug) == false 29 | expect(config.optOut) == false 30 | } 31 | 32 | it("init takes api key") { 33 | let config = PostHogConfig(apiKey: "123") 34 | 35 | expect(config.apiKey) == "123" 36 | } 37 | 38 | it("init takes host") { 39 | let config = PostHogConfig(apiKey: "123", host: "localhost:9000") 40 | 41 | expect(config.host) == URL(string: "localhost:9000")! 42 | } 43 | 44 | #if os(iOS) 45 | context("when initialized with default values for captureElementInteractions") { 46 | it("should enable autocapture by default") { 47 | let sut = PostHogConfig(apiKey: "123") 48 | expect(sut.captureElementInteractions).to(beFalse()) 49 | } 50 | } 51 | 52 | context("when customized") { 53 | it("should allow disabling autocapture") { 54 | let config = PostHogConfig(apiKey: "123") 55 | config.captureElementInteractions = false 56 | expect(config.captureElementInteractions).to(beFalse()) 57 | } 58 | } 59 | #endif 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /PostHogTests/PostHogStorageManagerTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostHogStorageManagerTest.swift 3 | // PostHogTests 4 | // 5 | // Created by Ben White on 22.03.23. 6 | // 7 | 8 | import Foundation 9 | import Nimble 10 | @testable import PostHog 11 | import Quick 12 | 13 | class PostHogStorageManagerTest: QuickSpec { 14 | func getSut() -> PostHogStorageManager { 15 | let config = PostHogConfig(apiKey: "123") 16 | return PostHogStorageManager(config) 17 | } 18 | 19 | override func spec() { 20 | it("Generates an anonymousId") { 21 | let sut = self.getSut() 22 | 23 | let anonymousId = sut.getAnonymousId() 24 | expect(anonymousId) != nil 25 | let secondAnonymousId = sut.getAnonymousId() 26 | expect(secondAnonymousId) == anonymousId 27 | 28 | sut.reset(true) 29 | } 30 | 31 | it("Uses the anonymousId for distinctId if not set") { 32 | let sut = self.getSut() 33 | 34 | let anonymousId = sut.getAnonymousId() 35 | let distinctId = sut.getDistinctId() 36 | expect(distinctId) == anonymousId 37 | 38 | let idToSet = UUID.v7().uuidString 39 | sut.setDistinctId(idToSet) 40 | let newAnonymousId = sut.getAnonymousId() 41 | let newDistinctId = sut.getDistinctId() 42 | expect(newAnonymousId) == anonymousId 43 | expect(newAnonymousId) != newDistinctId 44 | expect(newDistinctId) == idToSet 45 | 46 | sut.reset(true) 47 | } 48 | 49 | it("Can can accept id customization via config") { 50 | let config = PostHogConfig(apiKey: "123") 51 | let fixedUuid = UUID.v7() 52 | config.getAnonymousId = { _ in fixedUuid } 53 | let sut = PostHogStorageManager(config) 54 | let anonymousId = sut.getAnonymousId() 55 | expect(anonymousId) == fixedUuid.uuidString 56 | 57 | sut.reset(true) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /PostHogTests/Resources/input_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogTests/Resources/input_1.png -------------------------------------------------------------------------------- /PostHogTests/Resources/input_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogTests/Resources/input_2.png -------------------------------------------------------------------------------- /PostHogTests/Resources/input_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogTests/Resources/input_3.png -------------------------------------------------------------------------------- /PostHogTests/Resources/output_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogTests/Resources/output_1.webp -------------------------------------------------------------------------------- /PostHogTests/Resources/output_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogTests/Resources/output_2.webp -------------------------------------------------------------------------------- /PostHogTests/Resources/output_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trustwallet/posthog-ios/5a437567d9b6a5b4ad72b831d60c21639180ec39/PostHogTests/Resources/output_3.webp -------------------------------------------------------------------------------- /PostHogTests/TestUtils/TestError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestError.swift 3 | // PostHog 4 | // 5 | // Created by Yiannis Josephides on 18/12/2024. 6 | // 7 | 8 | struct TestError: Error, ExpressibleByStringLiteral, CustomStringConvertible { 9 | let description: String 10 | 11 | init(_ description: String) { 12 | self.description = description 13 | } 14 | 15 | init(stringLiteral value: StringLiteralType) { 16 | description = value 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PostHogTests/TestUtils/TestPostHog.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestPostHog.swift 3 | // PostHogTests 4 | // 5 | // Created by Ben White on 22.03.23. 6 | // 7 | 8 | import Foundation 9 | import PostHog 10 | import XCTest 11 | 12 | func getBatchedEvents(_ server: MockPostHogServer, timeout: TimeInterval = 15.0, failIfNotCompleted: Bool = true) -> [PostHogEvent] { 13 | let result = XCTWaiter.wait(for: [server.batchExpectation!], timeout: timeout) 14 | 15 | if result != XCTWaiter.Result.completed, failIfNotCompleted { 16 | XCTFail("The expected requests never arrived") 17 | } 18 | 19 | var events: [PostHogEvent] = [] 20 | for request in server.batchRequests.reversed() { 21 | let items = server.parsePostHogEvents(request) 22 | events.append(contentsOf: items) 23 | } 24 | 25 | return events 26 | } 27 | 28 | func waitDecideRequest(_ server: MockPostHogServer) { 29 | let result = XCTWaiter.wait(for: [server.decideExpectation!], timeout: 15) 30 | 31 | if result != XCTWaiter.Result.completed { 32 | XCTFail("The expected requests never arrived") 33 | } 34 | } 35 | 36 | func getDecideRequest(_ server: MockPostHogServer) -> [[String: Any]] { 37 | waitDecideRequest(server) 38 | 39 | var requests: [[String: Any]] = [] 40 | for request in server.decideRequests.reversed() { 41 | let item = server.parseRequest(request, gzip: false) 42 | requests.append(item!) 43 | } 44 | 45 | return requests 46 | } 47 | 48 | final class MockDate { 49 | var date = Date() 50 | } 51 | -------------------------------------------------------------------------------- /PostHogTests/TestUtils/URLSession+body.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLSession+body.swift 3 | // PostHogTests 4 | // 5 | // Created by Ben White on 10.04.23. 6 | // 7 | 8 | import Foundation 9 | 10 | extension URLRequest { 11 | func body() -> Data? { 12 | if httpBody != nil { 13 | return httpBody 14 | } 15 | 16 | guard let bodyStream = httpBodyStream else { return nil } 17 | 18 | bodyStream.open() 19 | 20 | // Will read 16 chars per iteration. Can use bigger buffer if needed 21 | let bufferSize = 16 22 | 23 | let buffer = UnsafeMutablePointer.allocate(capacity: bufferSize) 24 | 25 | var dat = Data() 26 | 27 | while bodyStream.hasBytesAvailable { 28 | let readDat = bodyStream.read(buffer, maxLength: bufferSize) 29 | dat.append(buffer, count: readDat) 30 | } 31 | 32 | buffer.deallocate() 33 | 34 | bodyStream.close() 35 | 36 | return dat 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build](https://img.shields.io/github/actions/workflow/status/PostHog/posthog-ios/build.yml?branch=main)](https://github.com/PostHog/posthog-ios/actions/workflows/build.yml?query=branch%3Amain) 2 | [![CocoaPods compadible](https://img.shields.io/cocoapods/v/PostHog.svg)](https://cocoapods.org/pods/PostHog) 3 | [![SwiftPM compatible](https://img.shields.io/badge/spm-compatible-brightgreen.svg?style=flat)](https://swift.org/package-manager) 4 | ![platforms](https://img.shields.io/cocoapods/p/PostHog.svg?style=flat) 5 | [![Swift Package Index](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FPostHog%2Fposthog-ios%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/PostHog/posthog-ios) 6 | 7 | # PostHog iOS 8 | 9 | Please see the main [PostHog docs](https://posthog.com/docs). 10 | 11 | Specifically, the [iOS docs](https://posthog.com/docs/libraries/ios) details. 12 | 13 | ## Questions? 14 | 15 | ### [Check out our community page.](https://posthog.com/posts) 16 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | Releasing 2 | ========= 3 | 4 | 1. Update the CHANGELOG.md with the version and date. 5 | 2. Choose a tag name (e.g. `3.0.0`), this is the version number of the release. 6 | 1. Preview releases follow the pattern `3.0.0-alpha.1`, `3.0.0-beta.1`, `3.0.0-RC.1` 7 | 2. Execute the script with the tag's name, the script will update the version file and create a tag. 8 | 9 | ```bash 10 | ./scripts/prepare-release.sh 3.0.0 11 | ``` 12 | 13 | 3. Go to [GH Releases](https://github.com/PostHog/posthog-ios/releases) 14 | 4. Choose a release name (e.g. `3.0.0`), and the tag you just created, ideally the same. 15 | 5. Write a description of the release. 16 | 6. Publish the release. 17 | 7. GH Action (release.yml) is doing everything else automatically. 18 | 1. SPM uses the tag name to determine the version, directly from the repo. 19 | 2. CocoaPods are published. 20 | 8. Done. 21 | -------------------------------------------------------------------------------- /dangerfile.js: -------------------------------------------------------------------------------- 1 | async function checkChangelog() { 2 | const changelogFile = "CHANGELOG.md"; 3 | 4 | // Check if skipped 5 | const skipChangelog = 6 | danger.github && (danger.github.pr.body + "").includes("#skip-changelog"); 7 | 8 | if (skipChangelog) { 9 | return; 10 | } 11 | 12 | // Check if current PR has an entry in changelog 13 | const changelogContents = await danger.github.utils.fileContents( 14 | changelogFile 15 | ); 16 | 17 | const hasChangelogEntry = RegExp(`#${danger.github.pr.number}\\b`).test( 18 | changelogContents 19 | ); 20 | 21 | if (hasChangelogEntry) { 22 | return; 23 | } 24 | 25 | // Report missing changelog entry 26 | fail( 27 | "Please consider adding a changelog entry for the next release.", 28 | changelogFile 29 | ); 30 | 31 | const prTitleFormatted = danger.github.pr.title 32 | .split(": ") 33 | .slice(-1)[0] 34 | .trim() 35 | .replace(/\.+$/, ""); 36 | 37 | markdown( 38 | ` 39 | ### Instructions and example for changelog 40 | Please add an entry to \`CHANGELOG.md\` to the "Next" section. Make sure the entry includes this PR's number. 41 | Example: 42 | \`\`\`markdown 43 | ## Next 44 | - ${prTitleFormatted} ([#${danger.github.pr.number}](${danger.github.pr.html_url})) 45 | \`\`\` 46 | If none of the above apply, you can opt out of this check by adding \`#skip-changelog\` to the PR description.`.trim() 47 | ); 48 | } 49 | 50 | async function checkAll() { 51 | const isDraft = danger.github.pr.mergeable_state === "draft"; 52 | 53 | if (isDraft) { 54 | return; 55 | } 56 | 57 | await checkChangelog(); 58 | } 59 | 60 | schedule(checkAll); 61 | -------------------------------------------------------------------------------- /scripts/bump-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # ./scripts/bump-version.sh 4 | # eg ./scripts/bump-version.sh "3.0.0-alpha.1" 5 | 6 | set -eux 7 | 8 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 9 | cd $SCRIPT_DIR/.. 10 | 11 | NEW_VERSION="$1" 12 | 13 | # Replace `postHogVersion` with the given version 14 | perl -pi -e "s/postHogVersion = \".*\"/postHogVersion = \"$NEW_VERSION\"/" PostHog/PostHogVersion.swift 15 | 16 | # Replace `s.version` with the given version 17 | perl -pi -e "s/s.version = \".*\"/s.version = \"$NEW_VERSION\"/" PostHog.podspec 18 | -------------------------------------------------------------------------------- /scripts/commit-code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | cd $SCRIPT_DIR/.. 6 | 7 | if [[ $(git status) == *"nothing to commit"* ]]; then 8 | echo "Nothing to commit." 9 | else 10 | echo "Going to push the changes." 11 | git fetch 12 | git commit -am "Update version" 13 | git push 14 | fi 15 | -------------------------------------------------------------------------------- /scripts/create-tag.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux 4 | 5 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 6 | cd $SCRIPT_DIR/.. 7 | 8 | NEW_VERSION="$1" 9 | 10 | git tag -a ${NEW_VERSION} -m "${NEW_VERSION}" 11 | git push && git push --tags 12 | -------------------------------------------------------------------------------- /scripts/prepare-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux 4 | 5 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 6 | cd $SCRIPT_DIR/.. 7 | 8 | NEW_VERSION="$1" 9 | 10 | # bump version 11 | ./scripts/bump-version.sh $NEW_VERSION 12 | 13 | # commit changes 14 | ./scripts/commit-code.sh 15 | 16 | # create and push tag 17 | ./scripts/create-tag.sh $NEW_VERSION 18 | -------------------------------------------------------------------------------- /scripts/update-tag.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | CURRENT_TAG="$1" 5 | TEMP_TAG="${CURRENT_TAG}-temp" 6 | GITHUB_BRANCH="${2}" 7 | 8 | echo "Going to push the tag changes." 9 | git config --global user.name 'PostHog Github Bot' 10 | git config --global user.email 'github-bot@posthog.com' 11 | git fetch 12 | git checkout ${GITHUB_BRANCH} 13 | # Create a new temporary tag after pushing the changes from the previous tag (bump version) 14 | git tag -a ${TEMP_TAG} -m "${TEMP_TAG}" 15 | # Remove the current tag 16 | git tag -d ${CURRENT_TAG} 17 | # Remove the current tag in remote machine 18 | git push --delete origin ${CURRENT_TAG} 19 | # Create a new tag that points to the temporary tag 20 | git tag ${CURRENT_TAG} ${TEMP_TAG} 21 | # Remove temporary tag 22 | git tag -d ${TEMP_TAG} 23 | # Propapate new tag to remote machine 24 | git push --tags 25 | -------------------------------------------------------------------------------- /vendor/libwebp/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Google Inc. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | * Neither the name of Google nor the names of its contributors may 16 | be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | -------------------------------------------------------------------------------- /vendor/libwebp/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | ------------------------------------ 3 | 4 | "These implementations" means the copyrightable works that implement the WebM 5 | codecs distributed by Google as part of the WebM Project. 6 | 7 | Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, 8 | royalty-free, irrevocable (except as stated in this section) patent license to 9 | make, have made, use, offer to sell, sell, import, transfer, and otherwise 10 | run, modify and propagate the contents of these implementations of WebM, where 11 | such license applies only to those patent claims, both currently owned by 12 | Google and acquired in the future, licensable by Google that are necessarily 13 | infringed by these implementations of WebM. This grant does not include claims 14 | that would be infringed only as a consequence of further modification of these 15 | implementations. If you or your agent or exclusive licensee institute or order 16 | or agree to the institution of patent litigation or any other patent 17 | enforcement activity against any entity (including a cross-claim or 18 | counterclaim in a lawsuit) alleging that any of these implementations of WebM 19 | or any code incorporated within any of these implementations of WebM 20 | constitute direct or contributory patent infringement, or inducement of 21 | patent infringement, then any patent rights granted to you under this License 22 | for these implementations of WebM shall terminate as of the date such 23 | litigation is filed. 24 | -------------------------------------------------------------------------------- /vendor/libwebp/color_cache_utils.c: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Color Cache for WebP Lossless 11 | // 12 | // Author: Jyrki Alakuijala (jyrki@google.com) 13 | 14 | #include 15 | #include 16 | #include "./color_cache_utils.h" 17 | #include "./utils.h" 18 | 19 | //------------------------------------------------------------------------------ 20 | // VP8LColorCache. 21 | 22 | int VP8LColorCacheInit(VP8LColorCache* const color_cache, int hash_bits) { 23 | const int hash_size = 1 << hash_bits; 24 | ASSERT(color_cache != NULL); 25 | ASSERT(hash_bits > 0); 26 | color_cache->colors_ = (uint32_t*)WebPSafeCalloc( 27 | (uint64_t)hash_size, sizeof(*color_cache->colors_)); 28 | if (color_cache->colors_ == NULL) return 0; 29 | color_cache->hash_shift_ = 32 - hash_bits; 30 | color_cache->hash_bits_ = hash_bits; 31 | return 1; 32 | } 33 | 34 | void VP8LColorCacheClear(VP8LColorCache* const color_cache) { 35 | if (color_cache != NULL) { 36 | WebPSafeFree(color_cache->colors_); 37 | color_cache->colors_ = NULL; 38 | } 39 | } 40 | 41 | void VP8LColorCacheCopy(const VP8LColorCache* const src, 42 | VP8LColorCache* const dst) { 43 | ASSERT(src != NULL); 44 | ASSERT(dst != NULL); 45 | ASSERT(src->hash_bits_ == dst->hash_bits_); 46 | memcpy(dst->colors_, src->colors_, 47 | ((size_t)1u << dst->hash_bits_) * sizeof(*dst->colors_)); 48 | } 49 | -------------------------------------------------------------------------------- /vendor/libwebp/common_dec.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Definitions and macros common to encoding and decoding 11 | // 12 | // Author: Skal (pascal.massimino@gmail.com) 13 | 14 | #ifndef WEBP_DEC_COMMON_DEC_H_ 15 | #define WEBP_DEC_COMMON_DEC_H_ 16 | 17 | // intra prediction modes 18 | enum { B_DC_PRED = 0, // 4x4 modes 19 | B_TM_PRED = 1, 20 | B_VE_PRED = 2, 21 | B_HE_PRED = 3, 22 | B_RD_PRED = 4, 23 | B_VR_PRED = 5, 24 | B_LD_PRED = 6, 25 | B_VL_PRED = 7, 26 | B_HD_PRED = 8, 27 | B_HU_PRED = 9, 28 | NUM_BMODES = B_HU_PRED + 1 - B_DC_PRED, // = 10 29 | 30 | // Luma16 or UV modes 31 | DC_PRED = B_DC_PRED, V_PRED = B_VE_PRED, 32 | H_PRED = B_HE_PRED, TM_PRED = B_TM_PRED, 33 | B_PRED = NUM_BMODES, // refined I4x4 mode 34 | NUM_PRED_MODES = 4, 35 | 36 | // special modes 37 | B_DC_PRED_NOTOP = 4, 38 | B_DC_PRED_NOLEFT = 5, 39 | B_DC_PRED_NOTOPLEFT = 6, 40 | NUM_B_DC_MODES = 7 }; 41 | 42 | enum { MB_FEATURE_TREE_PROBS = 3, 43 | NUM_MB_SEGMENTS = 4, 44 | NUM_REF_LF_DELTAS = 4, 45 | NUM_MODE_LF_DELTAS = 4, // I4x4, ZERO, *, SPLIT 46 | MAX_NUM_PARTITIONS = 8, 47 | // Probabilities 48 | NUM_TYPES = 4, // 0: i16-AC, 1: i16-DC, 2:chroma-AC, 3:i4-AC 49 | NUM_BANDS = 8, 50 | NUM_CTX = 3, 51 | NUM_PROBAS = 11 52 | }; 53 | 54 | #endif // WEBP_DEC_COMMON_DEC_H_ 55 | -------------------------------------------------------------------------------- /vendor/libwebp/dec_sse41.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // SSE4 version of some decoding functions. 11 | // 12 | // Author: Skal (pascal.massimino@gmail.com) 13 | 14 | #include "./dsp.h" 15 | 16 | #if defined(WEBP_USE_SSE41) 17 | 18 | #include 19 | #include "./utils.h" 20 | 21 | static void HE16_SSE41(uint8_t* dst) { // horizontal 22 | int j; 23 | const __m128i kShuffle3 = _mm_set1_epi8(3); 24 | for (j = 16; j > 0; --j) { 25 | const __m128i in = _mm_cvtsi32_si128(WebPMemToInt32(dst - 4)); 26 | const __m128i values = _mm_shuffle_epi8(in, kShuffle3); 27 | _mm_storeu_si128((__m128i*)dst, values); 28 | dst += BPS; 29 | } 30 | } 31 | 32 | //------------------------------------------------------------------------------ 33 | // Entry point 34 | 35 | extern void VP8DspInitSSE41(void); 36 | 37 | WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE41(void) { 38 | VP8PredLuma16[3] = HE16_SSE41; 39 | } 40 | 41 | #else // !WEBP_USE_SSE41 42 | 43 | WEBP_DSP_INIT_STUB(VP8DspInitSSE41) 44 | 45 | #endif // WEBP_USE_SSE41 46 | -------------------------------------------------------------------------------- /vendor/libwebp/filters_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Spatial prediction using various filters 11 | // 12 | // Author: Urvang (urvang@google.com) 13 | 14 | #pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" 15 | #ifndef WEBP_UTILS_FILTERS_UTILS_H_ 16 | #define WEBP_UTILS_FILTERS_UTILS_H_ 17 | 18 | #include "./types.h" 19 | #include "./dsp.h" 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | // Fast estimate of a potentially good filter. 26 | WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, 27 | int width, int height, int stride); 28 | 29 | #ifdef __cplusplus 30 | } // extern "C" 31 | #endif 32 | 33 | #endif // WEBP_UTILS_FILTERS_UTILS_H_ 34 | -------------------------------------------------------------------------------- /vendor/libwebp/huffman_utils.c: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Utilities for building and looking up Huffman trees. 11 | // 12 | // Author: Urvang Joshi (urvang@google.com) 13 | 14 | #include 15 | #include 16 | #include "./utils.h" 17 | #include "./format_constants.h" 18 | 19 | // Huffman data read via DecodeImageStream is represented in two (red and green) 20 | // bytes. 21 | #define MAX_HTREE_GROUPS 0x10000 22 | 23 | // Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits). 24 | // More commonly, the value is around ~280. 25 | #define MAX_CODE_LENGTHS_SIZE \ 26 | ((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES) 27 | // Cut-off value for switching between heap and stack allocation. 28 | #define SORTED_SIZE_CUTOFF 512 29 | -------------------------------------------------------------------------------- /vendor/libwebp/muxread.c: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Read APIs for mux. 11 | // 12 | // Authors: Urvang (urvang@google.com) 13 | // Vikas (vikasa@google.com) 14 | 15 | #include "./muxi.h" 16 | #include "./utils.h" 17 | 18 | //------------------------------------------------------------------------------ 19 | // Helper method(s). 20 | 21 | // Handy MACRO. 22 | #define SWITCH_ID_LIST(INDEX, LIST) \ 23 | do { \ 24 | if (idx == (INDEX)) { \ 25 | const WebPChunk* const chunk = ChunkSearchList((LIST), nth, \ 26 | kChunks[(INDEX)].tag); \ 27 | if (chunk) { \ 28 | *data = chunk->data_; \ 29 | return WEBP_MUX_OK; \ 30 | } else { \ 31 | return WEBP_MUX_NOT_FOUND; \ 32 | } \ 33 | } \ 34 | } while (0) 35 | 36 | #undef SWITCH_ID_LIST 37 | -------------------------------------------------------------------------------- /vendor/libwebp/quant_levels_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Alpha plane quantization utility 11 | // 12 | // Author: Vikas Arora (vikasa@google.com) 13 | 14 | #ifndef WEBP_UTILS_QUANT_LEVELS_UTILS_H_ 15 | #define WEBP_UTILS_QUANT_LEVELS_UTILS_H_ 16 | 17 | #include 18 | 19 | #include "./types.h" 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | // Replace the input 'data' of size 'width'x'height' with 'num-levels' 26 | // quantized values. If not NULL, 'sse' will contain the sum of squared error. 27 | // Valid range for 'num_levels' is [2, 256]. 28 | // Returns false in case of error (data is NULL, or parameters are invalid). 29 | int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, 30 | uint64_t* const sse); 31 | 32 | #ifdef __cplusplus 33 | } // extern "C" 34 | #endif 35 | 36 | #endif // WEBP_UTILS_QUANT_LEVELS_UTILS_H_ 37 | -------------------------------------------------------------------------------- /vendor/libwebp/random_utils.c: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Pseudo-random utilities 11 | // 12 | // Author: Skal (pascal.massimino@gmail.com) 13 | 14 | #include 15 | #include "./random_utils.h" 16 | 17 | //------------------------------------------------------------------------------ 18 | 19 | // 31b-range values 20 | static const uint32_t kRandomTable[VP8_RANDOM_TABLE_SIZE] = { 21 | 0x0de15230, 0x03b31886, 0x775faccb, 0x1c88626a, 0x68385c55, 0x14b3b828, 22 | 0x4a85fef8, 0x49ddb84b, 0x64fcf397, 0x5c550289, 0x4a290000, 0x0d7ec1da, 23 | 0x5940b7ab, 0x5492577d, 0x4e19ca72, 0x38d38c69, 0x0c01ee65, 0x32a1755f, 24 | 0x5437f652, 0x5abb2c32, 0x0faa57b1, 0x73f533e7, 0x685feeda, 0x7563cce2, 25 | 0x6e990e83, 0x4730a7ed, 0x4fc0d9c6, 0x496b153c, 0x4f1403fa, 0x541afb0c, 26 | 0x73990b32, 0x26d7cb1c, 0x6fcc3706, 0x2cbb77d8, 0x75762f2a, 0x6425ccdd, 27 | 0x24b35461, 0x0a7d8715, 0x220414a8, 0x141ebf67, 0x56b41583, 0x73e502e3, 28 | 0x44cab16f, 0x28264d42, 0x73baaefb, 0x0a50ebed, 0x1d6ab6fb, 0x0d3ad40b, 29 | 0x35db3b68, 0x2b081e83, 0x77ce6b95, 0x5181e5f0, 0x78853bbc, 0x009f9494, 30 | 0x27e5ed3c 31 | }; 32 | 33 | void VP8InitRandom(VP8Random* const rg, float dithering) { 34 | memcpy(rg->tab_, kRandomTable, sizeof(rg->tab_)); 35 | rg->index1_ = 0; 36 | rg->index2_ = 31; 37 | rg->amp_ = (dithering < 0.0) ? 0 38 | : (dithering > 1.0) ? (1 << VP8_RANDOM_DITHER_FIX) 39 | : (uint32_t)((1 << VP8_RANDOM_DITHER_FIX) * dithering); 40 | } 41 | 42 | //------------------------------------------------------------------------------ 43 | 44 | -------------------------------------------------------------------------------- /vendor/libwebp/sharpyuv_cpu.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | #include "./sharpyuv_cpu.h" 11 | 12 | // Include src/dsp/cpu.c to create SharpYuvGetCPUInfo from VP8GetCPUInfo. The 13 | // function pointer is renamed in sharpyuv_cpu.h. 14 | #include "./cpu.c" 15 | -------------------------------------------------------------------------------- /vendor/libwebp/sharpyuv_cpu.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | #pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" 11 | #ifndef WEBP_SHARPYUV_SHARPYUV_CPU_H_ 12 | #define WEBP_SHARPYUV_SHARPYUV_CPU_H_ 13 | 14 | #include "./sharpyuv.h" 15 | 16 | // Avoid exporting SharpYuvGetCPUInfo in shared object / DLL builds. 17 | // SharpYuvInit() replaces the use of the function pointer. 18 | #undef WEBP_EXTERN 19 | #define WEBP_EXTERN extern 20 | #define VP8GetCPUInfo SharpYuvGetCPUInfo 21 | #include "./cpu.h" 22 | 23 | #endif // WEBP_SHARPYUV_SHARPYUV_CPU_H_ 24 | -------------------------------------------------------------------------------- /vendor/libwebp/sharpyuv_dsp.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Speed-critical functions for Sharp YUV. 11 | 12 | #pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" 13 | #ifndef WEBP_SHARPYUV_SHARPYUV_DSP_H_ 14 | #define WEBP_SHARPYUV_SHARPYUV_DSP_H_ 15 | 16 | #include "./sharpyuv_cpu.h" 17 | #include "./types.h" 18 | 19 | extern uint64_t (*SharpYuvUpdateY)(const uint16_t* src, const uint16_t* ref, 20 | uint16_t* dst, int len, int bit_depth); 21 | extern void (*SharpYuvUpdateRGB)(const int16_t* src, const int16_t* ref, 22 | int16_t* dst, int len); 23 | extern void (*SharpYuvFilterRow)(const int16_t* A, const int16_t* B, int len, 24 | const uint16_t* best_y, uint16_t* out, 25 | int bit_depth); 26 | 27 | void SharpYuvInitDsp(void); 28 | 29 | #endif // WEBP_SHARPYUV_SHARPYUV_DSP_H_ 30 | -------------------------------------------------------------------------------- /vendor/libwebp/sharpyuv_gamma.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Gamma correction utilities. 11 | 12 | #pragma clang diagnostic ignored "-Wquoted-include-in-framework-header" 13 | #ifndef WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ 14 | #define WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ 15 | 16 | #include "./sharpyuv.h" 17 | #include "./types.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | // Initializes precomputed tables. Must be called once before calling 24 | // SharpYuvGammaToLinear or SharpYuvLinearToGamma. 25 | void SharpYuvInitGammaTables(void); 26 | 27 | // Converts a 'bit_depth'-bit gamma color value to a 16-bit linear value. 28 | uint32_t SharpYuvGammaToLinear(uint16_t v, int bit_depth, 29 | SharpYuvTransferFunctionType transfer_type); 30 | 31 | // Converts a 16-bit linear color value to a 'bit_depth'-bit gamma value. 32 | uint16_t SharpYuvLinearToGamma(uint32_t value, int bit_depth, 33 | SharpYuvTransferFunctionType transfer_type); 34 | 35 | #ifdef __cplusplus 36 | } // extern "C" 37 | #endif 38 | 39 | #endif // WEBP_SHARPYUV_SHARPYUV_GAMMA_H_ 40 | --------------------------------------------------------------------------------