├── .github
├── dependabot.yml
└── workflows
│ ├── codeql.yml
│ └── dependabot-alerts-to-slack.yml
├── .gitignore
├── .jazzy.yaml
├── .slather.yml
├── .swiftlint.auto.yml
├── .swiftlint.yml
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── AutocompleteClient.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── xcshareddata
│ └── xcschemes
│ └── ConstructorAutocomplete.xcscheme
├── AutocompleteClient.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ ├── IDEWorkspaceChecks.plist
│ └── WorkspaceSettings.xcsettings
├── AutocompleteClient
├── Constants
│ └── Constants.swift
├── ConstructorAutocomplete-Swift.h
├── FW
│ ├── API
│ │ ├── Data
│ │ │ └── TaskResponse.swift
│ │ ├── Error
│ │ │ └── NSError+Errors.swift
│ │ ├── Network
│ │ │ ├── Client
│ │ │ │ ├── NetworkClient.swift
│ │ │ │ └── URLSessionNetworkClient.swift
│ │ │ └── Response
│ │ │ │ ├── AutocompleteTaskResponse.swift
│ │ │ │ ├── BrowseFacetOptionsTaskResponse.swift
│ │ │ │ ├── BrowseFacetsTaskResponse.swift
│ │ │ │ ├── BrowseTaskResponse.swift
│ │ │ │ ├── NetworkResponse.swift
│ │ │ │ ├── QuizQuestionTaskResponse.swift
│ │ │ │ ├── QuizResultsTaskResponse.swift
│ │ │ │ ├── RecommendationsTaskResponse.swift
│ │ │ │ ├── SearchTaskResponse.swift
│ │ │ │ └── TrackingTaskResponse.swift
│ │ └── Parser
│ │ │ ├── Autocomplete
│ │ │ ├── AbstractAutocompleteResponseParser.swift
│ │ │ ├── CIOAutocompleteResponseParser.swift
│ │ │ └── ResponseParserDelegate.swift
│ │ │ ├── Browse
│ │ │ ├── AbstractBrowseFacetOptionsResponseParser.swift
│ │ │ ├── AbstractBrowseFacetsResponseParser.swift
│ │ │ ├── AbstractBrowseResponseParser.swift
│ │ │ ├── BrowseFacetOptionsResponseParser.swift
│ │ │ ├── BrowseFacetsResponseParser.swift
│ │ │ └── BrowseResponseParser.swift
│ │ │ ├── Quizzes
│ │ │ ├── AbstractQuizQuestionResponseParser.swift
│ │ │ ├── AbstractQuizResultsResponseParser.swift
│ │ │ ├── QuizQuestionResponseParser.swift
│ │ │ └── QuizResultsResponseParser.swift
│ │ │ ├── Recommendations
│ │ │ ├── AbstractRecommendationsResponseParser.swift
│ │ │ └── RecommendationsResponseParser.swift
│ │ │ └── Search
│ │ │ ├── AbstractSearchResponseParser.swift
│ │ │ └── SearchResponseParser.swift
│ ├── Config
│ │ ├── AutocompleteResultCount.swift
│ │ └── ConstructorIOConfig.swift
│ ├── DependencyInjection
│ │ └── DependencyContainer.swift
│ ├── Logging
│ │ ├── CIOLogger.swift
│ │ └── CIOPrintLogger.swift
│ ├── Logic
│ │ ├── ABTesting
│ │ │ └── CIOABTestCell.swift
│ │ ├── ClientID
│ │ │ ├── ClientIDGenerator.swift
│ │ │ ├── IDGenerator.swift
│ │ │ └── Persistence
│ │ │ │ ├── CIOClientIdLoader.swift
│ │ │ │ └── ClientIdLoader.swift
│ │ ├── Error
│ │ │ └── CIOError.swift
│ │ ├── Highlighting
│ │ │ ├── Attributes
│ │ │ │ ├── BoldAttributesProvider.swift
│ │ │ │ └── CIOHighlightingAttributesProvider.swift
│ │ │ └── CIOHighlighter.swift
│ │ ├── Query
│ │ │ ├── CIOQueryFilters.swift
│ │ │ ├── CIOQueryFmtOptions.swift
│ │ │ └── CIOQueryVariationsMap.swift
│ │ ├── Request
│ │ │ ├── Builder
│ │ │ │ ├── CIOAutocompleteQueryBuilder.swift
│ │ │ │ ├── CIOBrowseFacetOptionsQueryBuilder.swift
│ │ │ │ ├── CIOBrowseFacetsQueryBuilder.swift
│ │ │ │ ├── CIOBrowseGroupsQueryBuilder.swift
│ │ │ │ ├── CIOBrowseItemsQueryBuilder.swift
│ │ │ │ ├── CIOBrowseQueryBuilder.swift
│ │ │ │ ├── CIORecommendationsQueryBuilder.swift
│ │ │ │ ├── CIOSearchQueryBuilder.swift
│ │ │ │ ├── QueryItemCollection.swift
│ │ │ │ ├── RequestBuilder+QueryItems.swift
│ │ │ │ └── RequestBuilder.swift
│ │ │ ├── CIOAutocompleteQuery.swift
│ │ │ ├── CIOBrowseFacetOptionsQuery.swift
│ │ │ ├── CIOBrowseFacetsQuery.swift
│ │ │ ├── CIOBrowseGroupsQuery.swift
│ │ │ ├── CIOBrowseItemsQuery.swift
│ │ │ ├── CIOBrowseQuery.swift
│ │ │ ├── CIOGroupsSortOption.swift
│ │ │ ├── CIOItem.swift
│ │ │ ├── CIOQuizQuery.swift
│ │ │ ├── CIORecommendationsQuery.swift
│ │ │ ├── CIORequestData.swift
│ │ │ ├── CIOSearchQuery.swift
│ │ │ ├── CIOTrackAutocompleteSelectData.swift
│ │ │ ├── CIOTrackBrowseResultClickData.swift
│ │ │ ├── CIOTrackBrowseResultsLoadedData.swift
│ │ │ ├── CIOTrackConversionData.swift
│ │ │ ├── CIOTrackInputFocusData.swift
│ │ │ ├── CIOTrackItemDetailLoadData.swift
│ │ │ ├── CIOTrackPurchaseData.swift
│ │ │ ├── CIOTrackQuizConversionData.swift
│ │ │ ├── CIOTrackQuizResultClickData.swift
│ │ │ ├── CIOTrackQuizResultsLoadedData.swift
│ │ │ ├── CIOTrackRecommendationResultClickData.swift
│ │ │ ├── CIOTrackRecommendationResultsViewData.swift
│ │ │ ├── CIOTrackSearchResultClickData.swift
│ │ │ ├── CIOTrackSearchResultsLoadedData.swift
│ │ │ ├── CIOTrackSearchSubmitData.swift
│ │ │ └── CIOTrackSessionStartData.swift
│ │ ├── Result
│ │ │ ├── CIOAutocompleteResult.swift
│ │ │ ├── CIOCollectionData.swift
│ │ │ ├── CIOFilterFacet.swift
│ │ │ ├── CIOFilterFacetOption.swift
│ │ │ ├── CIOFilterGroup.swift
│ │ │ ├── CIOGroup.swift
│ │ │ ├── CIOQuizImages.swift
│ │ │ ├── CIOQuizOption.swift
│ │ │ ├── CIOQuizOptionAttribute.swift
│ │ │ ├── CIOQuizQuestion.swift
│ │ │ ├── CIOQuizResult.swift
│ │ │ ├── CIORecommendationsPod.swift
│ │ │ ├── CIORecommendationsStrategy.swift
│ │ │ ├── CIORefinedContent.swift
│ │ │ ├── CIOResult.swift
│ │ │ ├── CIOResultData.swift
│ │ │ ├── CIOResultFacet.swift
│ │ │ ├── CIOResultSourceData.swift
│ │ │ ├── CIOResultSources.swift
│ │ │ ├── CIOSearchRedirectInfo.swift
│ │ │ ├── CIOSortOption.swift
│ │ │ └── Responses
│ │ │ │ ├── CIOAutocompleteResponse.swift
│ │ │ │ ├── CIOBrowseFacetOptionsResponse.swift
│ │ │ │ ├── CIOBrowseFacetsResponse.swift
│ │ │ │ ├── CIOBrowseResponse.swift
│ │ │ │ ├── CIOQuizQuestionResponse.swift
│ │ │ │ ├── CIOQuizResultsResponse.swift
│ │ │ │ ├── CIORecommendationsResponse.swift
│ │ │ │ └── CIOSearchResponse.swift
│ │ ├── Session
│ │ │ ├── CIOSessionManager.swift
│ │ │ ├── CIOSessionManagerDelegate.swift
│ │ │ ├── Date
│ │ │ │ ├── CurrentTimeDateProvider.swift
│ │ │ │ └── DateProvider.swift
│ │ │ ├── Persistence
│ │ │ │ ├── CIOSessionLoader.swift
│ │ │ │ └── SessionLoader.swift
│ │ │ ├── Session.swift
│ │ │ └── SessionManager.swift
│ │ └── Worker
│ │ │ └── ConstructorIO.swift
│ └── UI
│ │ ├── CIOAutocompleteViewController.swift
│ │ ├── CustomCell
│ │ └── SearchResultCell.swift
│ │ ├── DefaultSearchItemCell.swift
│ │ ├── DefaultSearchItemCell.xib
│ │ ├── Delegate
│ │ └── CIOAutocompleteDelegate.swift
│ │ ├── Empty
│ │ ├── EmptyScreenView.swift
│ │ └── EmptyScreenView.xib
│ │ ├── Error
│ │ └── CIOErrorView.swift
│ │ ├── SearchBar
│ │ ├── CIOSearchBarDisplayMode.swift
│ │ ├── CustomSearchBar.swift
│ │ └── CustomSearchController.swift
│ │ ├── Style
│ │ └── CIOStyle.swift
│ │ ├── UICustomization
│ │ └── CIOAutocompleteUICustomization.swift
│ │ └── ViewModel
│ │ ├── AbstractAutocompleteViewModel.swift
│ │ ├── AutocompleteResult.swift
│ │ ├── AutocompleteViewModel.swift
│ │ ├── AutocompleteViewModelDelegate.swift
│ │ └── AutocompleteViewModelSection.swift
├── Info.plist
├── Resources
│ ├── constructor-io-error-icon.png
│ └── constructor-io-logo.png
└── Utils
│ ├── AutoLayout
│ └── UIView+AutoLayout.swift
│ ├── Collection
│ └── Collection+MapKeys.swift
│ ├── Color
│ └── UIColor+RGB.swift
│ ├── String
│ ├── NSAttributedString+Build.swift
│ ├── String+CharacterSetIterator.swift
│ ├── String+SearchSuggestionsSection.swift
│ └── String+Trim.swift
│ └── UI
│ ├── UISearchBar+TextField.swift
│ ├── UIView+FadeInOut.swift
│ └── UIView+FindSubview.swift
├── AutocompleteClientTests
├── FW
│ ├── API
│ │ ├── Error
│ │ │ └── ErrorTests.swift
│ │ └── Parser
│ │ │ ├── BrowseResponseParserTest.swift
│ │ │ ├── CIOAutocompleteResponseParserTests.swift
│ │ │ ├── MockResponseParserDelegate.swift
│ │ │ ├── RecommendationsResponseParserTests.swift
│ │ │ └── SearchResponseParserTests.swift
│ ├── Logic
│ │ ├── Highlighting
│ │ │ └── CIOHighlighterTests.swift
│ │ ├── Request
│ │ │ ├── AutocompleteQueryRequestBuilderTests.swift
│ │ │ ├── Matchers
│ │ │ │ ├── CIOBuilder.swift
│ │ │ │ └── Matcher+Regex.swift
│ │ │ ├── Mock
│ │ │ │ ├── AbstractAutocompleteViewModel+Mock.swift
│ │ │ │ ├── CIOGroup+Mock.swift
│ │ │ │ ├── CIOResult+Mock.swift
│ │ │ │ └── MockCommons.swift
│ │ │ ├── QueryItemCollection
│ │ │ │ └── QueryItemCollectionTests.swift
│ │ │ ├── QuizzesQueryRequestBuilderTests.swift
│ │ │ ├── RecommendationsQueryRequestBuilderTests.swift
│ │ │ ├── TrackAutocompleteSelectRequestBuilderTests.swift
│ │ │ ├── TrackBrowseResultClickRequestBuilder.swift
│ │ │ ├── TrackBrowseResultsLoadedRequestBuilder.swift
│ │ │ ├── TrackConversionRequestBuilderTests.swift
│ │ │ ├── TrackInputFocusRequestBuilderTests.swift
│ │ │ ├── TrackItemDetailLoadRequestBuilder.swift
│ │ │ ├── TrackPurchaseRequestBuilderTests.swift
│ │ │ ├── TrackQuizConversionRequestBuilder.swift
│ │ │ ├── TrackQuizResultClickRequestBuilder.swift
│ │ │ ├── TrackQuizResultsLoadedRequestBuilder.swift
│ │ │ ├── TrackRecommendationResultClickRequestBuilder.swift
│ │ │ ├── TrackRecommendationViewRequestBuilder.swift
│ │ │ ├── TrackSearchResultClickRequestBuilder.swift
│ │ │ ├── TrackSearchResultsLoadedRequestBuilder.swift
│ │ │ ├── TrackSearchSubmitRequestBuilder.swift
│ │ │ └── TrackSessionStartRequestBuilder.swift
│ │ ├── Session
│ │ │ ├── ClosureDateProvider.swift
│ │ │ ├── ClosureSessionManagerDelegate.swift
│ │ │ ├── NoSessionLoader.swift
│ │ │ └── SessionManagerTests.swift
│ │ └── Worker
│ │ │ ├── ConstructorIOABTestCellTests.swift
│ │ │ ├── ConstructorIOAutocompleteTests.swift
│ │ │ ├── ConstructorIOBrowseFacetOptionsTests.swift
│ │ │ ├── ConstructorIOBrowseFacetsTests.swift
│ │ │ ├── ConstructorIOBrowseGroupsTests.swift
│ │ │ ├── ConstructorIOBrowseItemsTests.swift
│ │ │ ├── ConstructorIOBrowseTests.swift
│ │ │ ├── ConstructorIOIntegrationTests.swift
│ │ │ ├── ConstructorIOQuizIntegrationTests.swift
│ │ │ ├── ConstructorIOQuizTests.swift
│ │ │ ├── ConstructorIORecommendationsTests.swift
│ │ │ ├── ConstructorIOSearchTests.swift
│ │ │ ├── ConstructorIOTests.swift
│ │ │ ├── ConstructorIOTrackAutocompleteSelectTests.swift
│ │ │ ├── ConstructorIOTrackBrowseResultClickTests.swift
│ │ │ ├── ConstructorIOTrackBrowseResultsLoadedTests.swift
│ │ │ ├── ConstructorIOTrackConversionTests.swift
│ │ │ ├── ConstructorIOTrackInputFocusTests.swift
│ │ │ ├── ConstructorIOTrackItemDetailLoadTests.swift
│ │ │ ├── ConstructorIOTrackPurchaseTests.swift
│ │ │ ├── ConstructorIOTrackQuizConversionTests.swift
│ │ │ ├── ConstructorIOTrackQuizResultClick.swift
│ │ │ ├── ConstructorIOTrackQuizResultsLoadedTests.swift
│ │ │ ├── ConstructorIOTrackRecommendationResultClickTests.swift
│ │ │ ├── ConstructorIOTrackRecommendationResultsViewTests.swift
│ │ │ ├── ConstructorIOTrackSearchResultClickTests.swift
│ │ │ ├── ConstructorIOTrackSearchResultsLoadedTests.swift
│ │ │ ├── ConstructorIOTrackSearchSubmitTests.swift
│ │ │ ├── ConstructorIOUserIDTests.swift
│ │ │ ├── ConstructorIOUserSegmentsTests.swift
│ │ │ └── SearchTests.swift
│ └── UI
│ │ ├── Other
│ │ └── DefaultSearchItemCellTests.swift
│ │ ├── SearchBar
│ │ └── SearchBarTextFieldTests.swift
│ │ ├── ViewController
│ │ └── AutocompleteViewControllerTests.swift
│ │ └── ViewModel
│ │ ├── AutocompleteResultCountTests.swift
│ │ ├── AutocompleteResultTests.swift
│ │ ├── AutocompleteViewModelTests.swift
│ │ └── ClosureAutocompleteViewModelDelegate.swift
├── Info.plist
├── Resources
│ ├── TestResource.swift
│ ├── response_browse_facet_options_json.json
│ ├── response_browse_facets_json.json
│ ├── response_browse_json.json
│ ├── response_json_multiple_groups.json
│ ├── response_json_multiple_sections.json
│ ├── response_json_single_result.json
│ ├── response_json_single_section.json
│ ├── response_quiz_next_question.json
│ ├── response_quiz_results.json
│ ├── response_recommendations.json
│ ├── response_search_json.json
│ ├── response_search_json_invalid_variations.json
│ ├── response_search_json_refined_content.json
│ ├── response_search_json_variation_custom_data.json
│ ├── response_search_json_variations.json
│ └── response_search_redirect.json
├── Test Utils
│ ├── Bundle
│ │ └── Bundle+Test.swift
│ ├── CIOResponse+SearchSuggestions.swift
│ ├── Constants
│ │ └── TestConstants.swift
│ ├── JSON
│ │ └── Data+ToJSON.swift
│ └── XCTest
│ │ ├── ExpectationHandler.swift
│ │ └── XCTest+TimeoutFail.swift
└── Utils
│ ├── Color
│ └── UIColorRGBConversionTests.swift
│ ├── String
│ ├── NSString+RangeOfCharactersTest.swift
│ ├── SearchSuggestionStringConversionTests.swift
│ ├── String+CharacterSetIteratorTests.swift
│ └── StringTrimTests.swift
│ └── UI
│ └── UIViewAnimationTests.swift
├── ConstructorAutocomplete.d
├── ConstructorAutocomplete.dia
├── ConstructorAutocomplete.podspec
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── Package.swift
├── Podfile
├── Podfile.lock
├── Pods
├── Kingfisher
│ ├── LICENSE
│ ├── README.md
│ └── Sources
│ │ ├── AnimatedImageView.swift
│ │ ├── Box.swift
│ │ ├── CacheSerializer.swift
│ │ ├── Filter.swift
│ │ ├── FormatIndicatedCacheSerializer.swift
│ │ ├── Image.swift
│ │ ├── ImageCache.swift
│ │ ├── ImageDownloader.swift
│ │ ├── ImageModifier.swift
│ │ ├── ImagePrefetcher.swift
│ │ ├── ImageProcessor.swift
│ │ ├── ImageTransition.swift
│ │ ├── ImageView+Kingfisher.swift
│ │ ├── Indicator.swift
│ │ ├── Kingfisher.h
│ │ ├── Kingfisher.swift
│ │ ├── KingfisherManager.swift
│ │ ├── KingfisherOptionsInfo.swift
│ │ ├── Placeholder.swift
│ │ ├── RequestModifier.swift
│ │ ├── Resource.swift
│ │ ├── String+MD5.swift
│ │ ├── ThreadHelper.swift
│ │ └── UIButton+Kingfisher.swift
├── Manifest.lock
├── OHHTTPStubs
│ ├── LICENSE
│ ├── OHHTTPStubs
│ │ └── Sources
│ │ │ ├── Compatibility.h
│ │ │ ├── JSON
│ │ │ ├── OHHTTPStubsResponse+JSON.h
│ │ │ └── OHHTTPStubsResponse+JSON.m
│ │ │ ├── NSURLSession
│ │ │ ├── NSURLRequest+HTTPBodyTesting.h
│ │ │ ├── NSURLRequest+HTTPBodyTesting.m
│ │ │ ├── OHHTTPStubs+NSURLSessionConfiguration.m
│ │ │ ├── OHHTTPStubsMethodSwizzling.h
│ │ │ └── OHHTTPStubsMethodSwizzling.m
│ │ │ ├── OHHTTPStubs.h
│ │ │ ├── OHHTTPStubs.m
│ │ │ ├── OHHTTPStubsResponse.h
│ │ │ ├── OHHTTPStubsResponse.m
│ │ │ ├── OHPathHelpers
│ │ │ ├── OHPathHelpers.h
│ │ │ └── OHPathHelpers.m
│ │ │ └── Swift
│ │ │ └── OHHTTPStubsSwift.swift
│ └── README.md
├── Pods.xcodeproj
│ └── project.pbxproj
└── Target Support Files
│ ├── Kingfisher
│ ├── Kingfisher-Info.plist
│ ├── Kingfisher-dummy.m
│ ├── Kingfisher-prefix.pch
│ ├── Kingfisher-umbrella.h
│ ├── Kingfisher.modulemap
│ └── Kingfisher.xcconfig
│ ├── OHHTTPStubs
│ ├── Info.plist
│ ├── OHHTTPStubs-Info.plist
│ ├── OHHTTPStubs-dummy.m
│ ├── OHHTTPStubs-prefix.pch
│ ├── OHHTTPStubs-umbrella.h
│ ├── OHHTTPStubs.modulemap
│ └── OHHTTPStubs.xcconfig
│ ├── Pods-AutocompleteClientTests
│ ├── Info.plist
│ ├── Pods-AutocompleteClientTests-Info.plist
│ ├── Pods-AutocompleteClientTests-acknowledgements.markdown
│ ├── Pods-AutocompleteClientTests-acknowledgements.plist
│ ├── Pods-AutocompleteClientTests-dummy.m
│ ├── Pods-AutocompleteClientTests-frameworks.sh
│ ├── Pods-AutocompleteClientTests-resources.sh
│ ├── Pods-AutocompleteClientTests-umbrella.h
│ ├── Pods-AutocompleteClientTests.debug.xcconfig
│ ├── Pods-AutocompleteClientTests.modulemap
│ └── Pods-AutocompleteClientTests.release.xcconfig
│ └── Pods-UserApplication
│ ├── Pods-UserApplication-Info.plist
│ ├── Pods-UserApplication-acknowledgements.markdown
│ ├── Pods-UserApplication-acknowledgements.plist
│ ├── Pods-UserApplication-dummy.m
│ ├── Pods-UserApplication-frameworks.sh
│ ├── Pods-UserApplication-umbrella.h
│ ├── Pods-UserApplication.debug.xcconfig
│ ├── Pods-UserApplication.modulemap
│ └── Pods-UserApplication.release.xcconfig
├── PrivacyInfo.xcprivacy
├── README.md
├── Resources
├── Assets.xcassets
│ ├── Contents.json
│ ├── icon_empty.imageset
│ │ ├── Contents.json
│ │ ├── icon_constructor.png
│ │ ├── icon_constructor@2x.png
│ │ └── icon_constructor@3x.png
│ └── icon_error.imageset
│ │ ├── Contents.json
│ │ ├── icon_error.png
│ │ ├── icon_error@2x.png
│ │ └── icon_error@3x.png
└── constructor-io-error-icon.png
├── SearchFWTestApp
├── SearchFWTestApp.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ └── contents.xcworkspacedata
├── SearchFWTestApp
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── Logo
│ │ │ └── Contents.json
│ ├── Base.lproj
│ │ └── Main.storyboard
│ ├── Info.plist
│ └── ViewController.swift
└── SearchFWTestAppTests
│ ├── Info.plist
│ └── SearchFWTestAppTests.swift
├── UserApplication
├── AppDelegate.swift
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Contents.json
│ ├── icon_cart.imageset
│ │ ├── Contents.json
│ │ ├── icon_cart.png
│ │ ├── icon_cart@2x.png
│ │ └── icon_cart@3x.png
│ ├── icon_clock.imageset
│ │ ├── Contents.json
│ │ └── icon_clock.png
│ ├── icon_error_yellow.imageset
│ │ ├── Contents.json
│ │ └── icon_error_yellow.png
│ ├── icon_filter.imageset
│ │ ├── Contents.json
│ │ └── icon_filter.png
│ ├── icon_gear.imageset
│ │ ├── Contents.json
│ │ └── icon-gear.png
│ ├── icon_help.imageset
│ │ ├── Contents.json
│ │ └── icon_help.png
│ ├── icon_logo.imageset
│ │ ├── Contents.json
│ │ └── constructor-io-logo.png
│ ├── icon_sign_error.imageset
│ │ ├── Contents.json
│ │ └── icon_sign_error.png
│ ├── icon_sort.imageset
│ │ ├── Contents.json
│ │ └── icon_sort.jpg
│ ├── icon_star.imageset
│ │ ├── Contents.json
│ │ └── icon_star.png
│ ├── img_logo.imageset
│ │ ├── Contents.json
│ │ └── img_logo.png
│ ├── sort_ascending.imageset
│ │ ├── Contents.json
│ │ └── arrow_up.png
│ └── sort_descending.imageset
│ │ ├── Contents.json
│ │ └── arrow_down.png
├── Common
│ ├── BadgeView.swift
│ ├── CartBarButtonItem.swift
│ └── Constructor
│ │ └── ConstructorIOProvider.swift
├── CustomHighlighting
│ └── CustomAttributesProvider.swift
├── CustomViews
│ ├── Background
│ │ └── CustomBackgroundView.xib
│ ├── Cell
│ │ ├── Class
│ │ │ └── CustomTableViewCellTwo.swift
│ │ └── Nib
│ │ │ ├── CustomTableViewCellOne.swift
│ │ │ └── CustomTableViewCellOne.xib
│ └── Error
│ │ ├── CustomErrorView.swift
│ │ └── CustomErrorView.xib
├── Info.plist
├── Screens
│ ├── Cart
│ │ ├── Logic
│ │ │ ├── Cart.swift
│ │ │ └── CartItem.swift
│ │ ├── Persistence
│ │ │ └── CartPersistence.swift
│ │ ├── UI
│ │ │ ├── CartItemTableViewCell.swift
│ │ │ ├── CartItemTableViewCell.xib
│ │ │ ├── CartViewController.swift
│ │ │ └── CartViewController.xib
│ │ └── ViewModel
│ │ │ ├── CartItemViewModel.swift
│ │ │ ├── CartViewModel.swift
│ │ │ └── Quantity.swift
│ ├── Details
│ │ ├── UI
│ │ │ ├── DetailsViewController.swift
│ │ │ └── DetailsViewController.xib
│ │ └── ViewModel
│ │ │ └── DetailsViewModel.swift
│ ├── Filters
│ │ ├── Delegate
│ │ │ └── FiltersSelectionDelegate.swift
│ │ ├── UI
│ │ │ ├── Cells
│ │ │ │ ├── FilterTableViewCell.swift
│ │ │ │ └── FilterTableViewCell.xib
│ │ │ ├── Header
│ │ │ │ ├── Delegate
│ │ │ │ │ └── FilterHeaderDelegate.swift
│ │ │ │ ├── FilterHeaderView.swift
│ │ │ │ └── FilterHeaderView.xib
│ │ │ └── ViewController
│ │ │ │ ├── FiltersViewController.swift
│ │ │ │ └── FiltersViewController.xib
│ │ └── ViewModel
│ │ │ ├── FacetOptionViewModel.swift
│ │ │ ├── FacetViewModel.swift
│ │ │ └── FiltersViewModel.swift
│ ├── Search
│ │ ├── UI
│ │ │ ├── SearchCollectionViewCell.swift
│ │ │ ├── SearchCollectionViewCell.xib
│ │ │ ├── SearchTableViewCell.swift
│ │ │ ├── SearchTableViewCell.xib
│ │ │ ├── SearchViewController.swift
│ │ │ └── SearchViewController.xib
│ │ └── ViewModel
│ │ │ ├── SearchResultViewModel.swift
│ │ │ └── SearchViewModel.swift
│ └── Sort
│ │ ├── Delegate
│ │ └── SortSelectionDelegate.swift
│ │ ├── UI
│ │ ├── SortOptionTableViewCell.swift
│ │ ├── SortOptionTableViewCell.xib
│ │ ├── SortOptionsViewController.swift
│ │ ├── SortOptionsViewController.xib
│ │ └── UIImage
│ │ │ └── UIImage+Sort.swift
│ │ └── ViewModel
│ │ ├── SortOptionViewModel.swift
│ │ └── SortViewModel.swift
└── Utils
│ └── UI
│ ├── UIColor+RGB.swift
│ ├── UIFont+AppFonts.swift
│ └── UIView+AutoLayout.swift
├── UserApplicationTests
├── DataSource
│ ├── AutocompleteDataSourceTests.swift
│ └── AutocompleteDataSourceWrapper.swift
├── Delegate
│ ├── AutocompleteDelegateTests.swift
│ └── AutocompleteDelegateWrapper.swift
├── Info.plist
└── Utils
│ └── CIOAutocompleteViewController+Show.swift
├── coverage.all.sh
├── coverage.core.sh
└── docs
├── Classes.html
├── Classes
├── AutocompleteResult.html
├── AutocompleteViewModel.html
├── BoldAttributesProvider.html
├── CIOAutocompleteQueryBuilder.html
├── CIOAutocompleteResult.html
├── CIOAutocompleteViewController.html
├── CIOBrowseFacetOptionsQueryBuilder.html
├── CIOBrowseFacetsQueryBuilder.html
├── CIOBrowseGroupsQueryBuilder.html
├── CIOBrowseItemsQueryBuilder.html
├── CIOBrowseQueryBuilder.html
├── CIOCollectionData.html
├── CIOFilterGroup.html
├── CIOGroup.html
├── CIOHighlighter.html
├── CIOPrintLogger.html
├── CIORecommendationsQueryBuilder.html
├── CIOResult.html
├── CIOResultSourceData.html
├── CIOResultSources.html
├── CIOSearchQueryBuilder.html
├── ConstructorIO.html
├── CustomSearchBar.html
├── CustomSearchController.html
├── DefaultSearchItemCell.html
├── EmptyScreenView.html
├── Session.html
└── TaskResponse.html
├── Client.html
├── Constructor IO Client.html
├── Enums.html
├── Enums
├── CIOError.html
├── CIOSearchBarDisplayMode.html
└── CIOSortOrder.html
├── Extensions.html
├── Extensions
└── UISearchBar.html
├── Other Classes.html
├── Other Enums.html
├── Other Protocols.html
├── Other Structs.html
├── Protocols.html
├── Protocols
├── AbstractAutocompleteViewModel.html
├── AutocompleteViewModelDelegate.html
├── CIOAutocompleteCell.html
├── CIOAutocompleteDelegate.html
├── CIOAutocompleteUICustomization.html
├── CIOErrorView.html
├── CIOHighlightingAttributesProvider.html
├── CIOLogger.html
├── CIOSessionManagerDelegate.html
└── SessionManager.html
├── Response Structures.html
├── Result Classes.html
├── Result Request Builders.html
├── Result Request Classes.html
├── Result Request Objects.html
├── Result Request Structures.html
├── Result Structures & Classes.html
├── Structs.html
├── Structs
├── AutocompleteResultCount.html
├── AutocompleteViewModelSection.html
├── CIOABTestCell.html
├── CIOAutocompleteQuery.html
├── CIOAutocompleteResponse.html
├── CIOBrowseFacetOptionsQuery.html
├── CIOBrowseFacetOptionsResponse.html
├── CIOBrowseFacetsQuery.html
├── CIOBrowseFacetsResponse.html
├── CIOBrowseGroupsQuery.html
├── CIOBrowseItemsQuery.html
├── CIOBrowseQuery.html
├── CIOBrowseResponse.html
├── CIOFilterFacet.html
├── CIOFilterFacetOption.html
├── CIOQueryFilters.html
├── CIOQuizImages.html
├── CIOQuizOption.html
├── CIOQuizOptionAttribute.html
├── CIOQuizQuery.html
├── CIOQuizQuestion.html
├── CIOQuizQuestionResponse.html
├── CIOQuizResult.html
├── CIOQuizResultsResponse.html
├── CIORecommendationsPod.html
├── CIORecommendationsQuery.html
├── CIORecommendationsResponse.html
├── CIORecommendationsStrategy.html
├── CIORefinedContent.html
├── CIOResultData.html
├── CIOResultFacet.html
├── CIOSearchQuery.html
├── CIOSearchRedirectInfo.html
├── CIOSearchResponse.html
├── CIOSortOption.html
└── ConstructorIOConfig.html
├── Tracking Request Classes.html
├── Typealiases.html
├── badge.svg
├── css
├── highlight.css
└── jazzy.css
├── docsets
├── ConstructorAutocomplete.docset
│ └── Contents
│ │ ├── Info.plist
│ │ └── Resources
│ │ ├── Documents
│ │ ├── Classes.html
│ │ ├── Classes
│ │ │ ├── AutocompleteResult.html
│ │ │ ├── AutocompleteViewModel.html
│ │ │ ├── BoldAttributesProvider.html
│ │ │ ├── CIOAutocompleteQueryBuilder.html
│ │ │ ├── CIOAutocompleteResult.html
│ │ │ ├── CIOAutocompleteViewController.html
│ │ │ ├── CIOBrowseFacetOptionsQueryBuilder.html
│ │ │ ├── CIOBrowseFacetsQueryBuilder.html
│ │ │ ├── CIOBrowseGroupsQueryBuilder.html
│ │ │ ├── CIOBrowseItemsQueryBuilder.html
│ │ │ ├── CIOBrowseQueryBuilder.html
│ │ │ ├── CIOCollectionData.html
│ │ │ ├── CIOFilterGroup.html
│ │ │ ├── CIOGroup.html
│ │ │ ├── CIOHighlighter.html
│ │ │ ├── CIOPrintLogger.html
│ │ │ ├── CIORecommendationsQueryBuilder.html
│ │ │ ├── CIOResult.html
│ │ │ ├── CIOResultSourceData.html
│ │ │ ├── CIOResultSources.html
│ │ │ ├── CIOSearchQueryBuilder.html
│ │ │ ├── ConstructorIO.html
│ │ │ ├── CustomSearchBar.html
│ │ │ ├── CustomSearchController.html
│ │ │ ├── DefaultSearchItemCell.html
│ │ │ ├── EmptyScreenView.html
│ │ │ ├── Session.html
│ │ │ └── TaskResponse.html
│ │ ├── Client.html
│ │ ├── Constructor IO Client.html
│ │ ├── Enums.html
│ │ ├── Enums
│ │ │ ├── CIOError.html
│ │ │ ├── CIOSearchBarDisplayMode.html
│ │ │ └── CIOSortOrder.html
│ │ ├── Extensions.html
│ │ ├── Extensions
│ │ │ └── UISearchBar.html
│ │ ├── Other Classes.html
│ │ ├── Other Enums.html
│ │ ├── Other Protocols.html
│ │ ├── Other Structs.html
│ │ ├── Protocols.html
│ │ ├── Protocols
│ │ │ ├── AbstractAutocompleteViewModel.html
│ │ │ ├── AutocompleteViewModelDelegate.html
│ │ │ ├── CIOAutocompleteCell.html
│ │ │ ├── CIOAutocompleteDelegate.html
│ │ │ ├── CIOAutocompleteUICustomization.html
│ │ │ ├── CIOErrorView.html
│ │ │ ├── CIOHighlightingAttributesProvider.html
│ │ │ ├── CIOLogger.html
│ │ │ ├── CIOSessionManagerDelegate.html
│ │ │ └── SessionManager.html
│ │ ├── Response Structures.html
│ │ ├── Result Classes.html
│ │ ├── Result Request Builders.html
│ │ ├── Result Request Classes.html
│ │ ├── Result Request Objects.html
│ │ ├── Result Request Structures.html
│ │ ├── Result Structures & Classes.html
│ │ ├── Structs.html
│ │ ├── Structs
│ │ │ ├── AutocompleteResultCount.html
│ │ │ ├── AutocompleteViewModelSection.html
│ │ │ ├── CIOABTestCell.html
│ │ │ ├── CIOAutocompleteQuery.html
│ │ │ ├── CIOAutocompleteResponse.html
│ │ │ ├── CIOBrowseFacetOptionsQuery.html
│ │ │ ├── CIOBrowseFacetOptionsResponse.html
│ │ │ ├── CIOBrowseFacetsQuery.html
│ │ │ ├── CIOBrowseFacetsResponse.html
│ │ │ ├── CIOBrowseGroupsQuery.html
│ │ │ ├── CIOBrowseItemsQuery.html
│ │ │ ├── CIOBrowseQuery.html
│ │ │ ├── CIOBrowseResponse.html
│ │ │ ├── CIOFilterFacet.html
│ │ │ ├── CIOFilterFacetOption.html
│ │ │ ├── CIOQueryFilters.html
│ │ │ ├── CIOQuizImages.html
│ │ │ ├── CIOQuizOption.html
│ │ │ ├── CIOQuizOptionAttribute.html
│ │ │ ├── CIOQuizQuery.html
│ │ │ ├── CIOQuizQuestion.html
│ │ │ ├── CIOQuizQuestionResponse.html
│ │ │ ├── CIOQuizResult.html
│ │ │ ├── CIOQuizResultsResponse.html
│ │ │ ├── CIORecommendationsPod.html
│ │ │ ├── CIORecommendationsQuery.html
│ │ │ ├── CIORecommendationsResponse.html
│ │ │ ├── CIORecommendationsStrategy.html
│ │ │ ├── CIORefinedContent.html
│ │ │ ├── CIOResultData.html
│ │ │ ├── CIOResultFacet.html
│ │ │ ├── CIOSearchQuery.html
│ │ │ ├── CIOSearchRedirectInfo.html
│ │ │ ├── CIOSearchResponse.html
│ │ │ ├── CIOSortOption.html
│ │ │ └── ConstructorIOConfig.html
│ │ ├── Tracking Request Classes.html
│ │ ├── Typealiases.html
│ │ ├── badge.svg
│ │ ├── css
│ │ │ ├── highlight.css
│ │ │ └── jazzy.css
│ │ ├── img
│ │ │ ├── carat.png
│ │ │ ├── dash.png
│ │ │ ├── gh.png
│ │ │ └── spinner.gif
│ │ ├── index.html
│ │ ├── js
│ │ │ ├── jazzy.js
│ │ │ ├── jazzy.search.js
│ │ │ ├── jquery.min.js
│ │ │ ├── lunr.min.js
│ │ │ └── typeahead.jquery.js
│ │ ├── search.json
│ │ └── undocumented.json
│ │ └── docSet.dsidx
└── ConstructorAutocomplete.tgz
├── img
├── carat.png
├── dash.png
├── gh.png
└── spinner.gif
├── index.html
├── js
├── jazzy.js
├── jazzy.search.js
├── jquery.min.js
├── lunr.min.js
└── typeahead.jquery.js
├── search.json
└── undocumented.json
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | updates:
4 | # Maintain dependencies for ruby packages
5 | - package-ecosystem: "bundler"
6 | directory: "/"
7 | schedule:
8 | interval: "daily"
9 | # Disable version updates for ruby dependencies
10 | # This option has no impact on security updates, which have a separate, internal limit of ten open pull requests.
11 | open-pull-requests-limit: 0
12 | reviewers:
13 | - "crgee1" # Chris
14 | - "jjl014" # Jimmy
15 |
--------------------------------------------------------------------------------
/.github/workflows/dependabot-alerts-to-slack.yml:
--------------------------------------------------------------------------------
1 | name: 'Check for Dependabot alerts & send them to Slack'
2 |
3 | on:
4 | schedule:
5 | - cron: '30 16 * * *' # every day at 9:30 am PST
6 | workflow_dispatch: # to have the option to run this ad-hoc
7 |
8 | jobs:
9 | main:
10 | uses: Constructor-io/customer-integrations-public-github-workflows/.github/workflows/dependabot-alerts-to-slack.yml@main
11 | secrets:
12 | github-app-id: ${{ vars.DEPENDABOT_ACCESS_APP_ID }}
13 | github-app-private-key: ${{ secrets.DEPENDABOT_ACCESS_PRIVATE_KEY }}
14 | slack-webhook: ${{ secrets.CUSTOMER_INTEGRATIONS_SLACK_WEBHOOK }}
15 |
16 |
--------------------------------------------------------------------------------
/.slather.yml:
--------------------------------------------------------------------------------
1 | # .slather.yml
2 |
3 | scheme: ConstructorAutocomplete
4 | workspace: AutocompleteClient.xcworkspace
5 | xcodeproj: AutocompleteClient.xcodeproj
--------------------------------------------------------------------------------
/.swiftlint.auto.yml:
--------------------------------------------------------------------------------
1 | included:
2 | - AutocompleteClient
3 | - AutocompleteClientTests
4 | excluded:
5 | - Tests/SwiftLintFrameworkTests/Resources
6 | analyzer_rules:
7 | - unused_import
8 | - unused_private_declaration
9 | disabled_rules:
10 | - line_length
11 | - identifier_name
12 | - number_separator
13 | - unused_closure_parameter
14 | - type_name
15 | opt_in_rules:
16 | - control_statement
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | included:
2 | - AutocompleteClient
3 | - AutocompleteClientTests
4 | excluded:
5 | - Tests/SwiftLintFrameworkTests/Resources
6 | analyzer_rules:
7 | - unused_import
8 | - unused_private_declaration
9 | disabled_rules:
10 | - line_length
11 | - identifier_name
12 | - number_separator
13 | - unused_closure_parameter
14 | - type_name
15 | opt_in_rules:
16 | - anyobject_protocol
17 | - array_init
18 | - attributes
19 | - closure_end_indentation
20 | - closure_spacing
21 | - collection_alignment
22 | - contains_over_first_not_nil
23 | - empty_count
24 | - empty_string
25 | - empty_xctest_method
26 | - explicit_init
27 | - extension_access_modifier
28 | - fallthrough
29 | - fatal_error_message
30 | - file_header
31 | - file_name
32 | - first_where
33 | - identical_operands
34 | - joined_default_parameter
35 | - let_var_whitespace
36 | - literal_expression_end_indentation
37 | - lower_acl_than_parent
38 | - nimble_operator
39 | - number_separator
40 | - object_literal
41 | - operator_usage_whitespace
42 | - overridden_super_call
43 | - override_in_extension
44 | - pattern_matching_keywords
45 | - private_action
46 | - private_outlet
47 | - prohibited_interface_builder
48 | - prohibited_super_call
49 | - quick_discouraged_call
50 | - quick_discouraged_focused_test
51 | - quick_discouraged_pending_test
52 | - redundant_nil_coalescing
53 | - redundant_type_annotation
54 | - single_test_class
55 | - sorted_first_last
56 | - sorted_imports
57 | - static_operator
58 | - unavailable_function
59 | - unneeded_parentheses_in_closure_argument
60 | - untyped_error_in_catch
61 | - vertical_parameter_alignment_on_call
62 | - yoda_condition
63 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AutocompleteClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AutocompleteClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AutocompleteClient.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Original
7 | PreviewsEnabled
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/AutocompleteClient.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/AutocompleteClient.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AutocompleteClient.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AutocompleteClient/ConstructorAutocomplete-Swift.h:
--------------------------------------------------------------------------------
1 | //
2 | // ConstructorAutocomplete-Swift.h
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for AutocompleteClient.
12 | FOUNDATION_EXPORT double AutocompleteClientVersionNumber;
13 |
14 | //! Project version string for AutocompleteClient.
15 | FOUNDATION_EXPORT const unsigned char AutocompleteClientVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Data/TaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaskResponse.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Task response must be constructed through one of the two constructors so it's impossible to have a response
13 | that has no data and no error
14 | */
15 | public class TaskResponse {
16 | public let data: T?
17 | public let error: E?
18 |
19 | public init(data: T) {
20 | self.data = data
21 | self.error = nil
22 | }
23 |
24 | public init(error: E) {
25 | self.data = nil
26 | self.error = error
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Error/NSError+Errors.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSError+Unknown.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | let kConstructorUnknownErrorCode = 0xf
12 | let kConstructorJSONErrorCode = 0xf0
13 |
14 | extension NSError {
15 | class func unknownError() -> NSError {
16 | return NSError(domain: "unknownError", code: kConstructorUnknownErrorCode, userInfo: nil)
17 | }
18 |
19 | class func jsonParseError() -> NSError {
20 | return NSError(domain: "jsonParseError", code: kConstructorJSONErrorCode, userInfo: nil)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Client/NetworkClient.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NetworkClient.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol NetworkClient {
12 |
13 | func execute(_ request: URLRequest, completionHandler: @escaping (_ response: NetworkResponse) -> Void)
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/AutocompleteTaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteTaskResponse.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public class AutocompleteTaskResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/BrowseFacetOptionsTaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BrowseFacetOptionsTaskResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class BrowseFacetOptionsTaskResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/BrowseFacetsTaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BrowseFacetsTaskResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class BrowseFacetsTaskResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/BrowseTaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchTaskResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class BrowseTaskResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/NetworkResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NetworkResponse.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public class NetworkResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/QuizQuestionTaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // QuizQuestionTaskResponse.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public class QuizQuestionTaskResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/QuizResultsTaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // QuizResultsTaskResponse.swift
3 | // ConstructorAutocomplete
4 | //
5 | // Created by Islam Mouatafa on 11/10/22.
6 | // Copyright © 2022 xd. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public class QuizResultsTaskResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/RecommendationsTaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RecommendationsTaskResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class RecommendationsTaskResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/SearchTaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchTaskResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class SearchTaskResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Network/Response/TrackingTaskResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TrackingTaskResponse.swift
3 | // ConstructorAutocomplete
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class TrackingTaskResponse: TaskResponse {}
12 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Autocomplete/AbstractAutocompleteResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AbstractAutocompleteResponseParser.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol AbstractAutocompleteResponseParser {
12 |
13 | var delegate: ResponseParserDelegate? { get set }
14 | var maxGroups: Int? { get set }
15 | func parse(autocompleteResponseData: Data) throws -> CIOAutocompleteResponse
16 | }
17 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Autocomplete/ResponseParserDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ResponseParserDelegate.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol ResponseParserDelegate: AnyObject {
12 | func shouldParseResult(result: CIOResult, inGroup group: CIOGroup?) -> Bool?
13 | func maximumGroupsShownPerResult(result: CIOResult, at index: Int) -> Int
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Browse/AbstractBrowseFacetOptionsResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AbstractBrowseFacetOptionsResponseParser.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol AbstractBrowseFacetOptionsResponseParser {
12 |
13 | func parse(browseFacetOptionsResponseData: Data) throws -> CIOBrowseFacetOptionsResponse
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Browse/AbstractBrowseFacetsResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AbstractBrowseFacetsResponseParser.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol AbstractBrowseFacetsResponseParser {
12 |
13 | func parse(browseFacetsResponseData: Data) throws -> CIOBrowseFacetsResponse
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Browse/AbstractBrowseResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AbstractBrowseResponseParser.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol AbstractBrowseResponseParser {
12 |
13 | func parse(browseResponseData: Data) throws -> CIOBrowseResponse
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Browse/BrowseFacetOptionsResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BrowseFacetOptionsResponseParser.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | class BrowseFacetOptionsResponseParser: AbstractBrowseFacetOptionsResponseParser {
12 | func parse(browseFacetOptionsResponseData: Data) throws -> CIOBrowseFacetOptionsResponse {
13 |
14 | do {
15 | let json = try JSONSerialization.jsonObject(with: browseFacetOptionsResponseData) as? JSONObject
16 |
17 | guard let response = json?["response"] as? JSONObject else {
18 | throw CIOError(errorType: .invalidResponse)
19 | }
20 |
21 | let facetsObj: [JSONObject]? = response["facets"] as? [JSONObject]
22 |
23 | let facets: [CIOFilterFacet] = (facetsObj)?.compactMap { obj in return CIOFilterFacet(json: obj) } ?? []
24 | let resultID = json?["result_id"] as? String ?? ""
25 |
26 | return CIOBrowseFacetOptionsResponse(
27 | facets: facets,
28 | resultID: resultID
29 | )
30 | } catch {
31 | throw CIOError(errorType: .invalidResponse)
32 | }
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Browse/BrowseFacetsResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BrowseFacetsResponseParser.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | class BrowseFacetsResponseParser: AbstractBrowseFacetsResponseParser {
12 | func parse(browseFacetsResponseData: Data) throws -> CIOBrowseFacetsResponse {
13 |
14 | do {
15 | let json = try JSONSerialization.jsonObject(with: browseFacetsResponseData) as? JSONObject
16 |
17 | guard let response = json?["response"] as? JSONObject else {
18 | throw CIOError(errorType: .invalidResponse)
19 | }
20 |
21 | let facetsObj: [JSONObject]? = response["facets"] as? [JSONObject]
22 |
23 | let facets: [CIOFilterFacet] = (facetsObj)?.compactMap { obj in return CIOFilterFacet(json: obj) } ?? []
24 | let totalNumResults = response["total_num_results"] as? Int ?? 0
25 | let resultID = json?["result_id"] as? String ?? ""
26 |
27 | return CIOBrowseFacetsResponse(
28 | facets: facets,
29 | totalNumResults: totalNumResults,
30 | resultID: resultID
31 | )
32 | } catch {
33 | throw CIOError(errorType: .invalidResponse)
34 | }
35 |
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Quizzes/AbstractQuizQuestionResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AbstractQuizQuestionResponseParser.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol AbstractQuizQuestionResponseParser {
12 |
13 | func parse(quizQuestionResponseData: Data) throws -> CIOQuizQuestionResponse
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Quizzes/AbstractQuizResultsResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AbstractQuizResultsResponseParser.swift
3 | // ConstructorAutocomplete
4 | //
5 | // Created by Islam Mouatafa on 11/11/22.
6 | // Copyright © 2022 xd. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | protocol AbstractQuizResultsResponseParser {
12 |
13 | func parse(quizResultsResponseData: Data) throws -> CIOQuizResultsResponse
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Quizzes/QuizQuestionResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // QuizQuestionResponseParser.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | class QuizQuestionResponseParser: AbstractQuizQuestionResponseParser {
12 | func parse(quizQuestionResponseData: Data) throws -> CIOQuizQuestionResponse {
13 |
14 | do {
15 | let json = try JSONSerialization.jsonObject(with: quizQuestionResponseData) as? JSONObject
16 | let quizVersionID = json?["quiz_version_id"] as? String ?? ""
17 | let quizID = json?["quiz_id"] as? String ?? ""
18 | let quizSessionID = json?["quiz_session_id"] as? String ?? ""
19 | let nextQuestion = CIOQuizQuestion(json: json?["next_question"] as? JSONObject ?? [:])
20 |
21 | return CIOQuizQuestionResponse(
22 | nextQuestion: nextQuestion!,
23 | quizVersionID: quizVersionID,
24 | quizSessionID: quizSessionID,
25 | quizID: quizID
26 | )
27 | } catch {
28 | throw CIOError(errorType: .invalidResponse)
29 | }
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Recommendations/AbstractRecommendationsResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AbstractRecommendationsResponseParser.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol AbstractRecommendationsResponseParser {
12 |
13 | func parse(recommendationsResponseData: Data) throws -> CIORecommendationsResponse
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/API/Parser/Search/AbstractSearchResponseParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AbstractSearchResponseParser.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol AbstractSearchResponseParser {
12 |
13 | func parse(searchResponseData: Data) throws -> CIOSearchResponse
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Config/AutocompleteResultCount.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteResultCount.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating the result count
13 | */
14 | public struct AutocompleteResultCount {
15 | /**
16 | The total number of results to request for
17 | */
18 | public let numResults: Int?
19 |
20 | /**
21 | The number of results to request for per section
22 | */
23 | public let numResultsForSection: [String: Int]?
24 |
25 | /**
26 | Create a result count object with a set number of results to be returned overall
27 |
28 | - Parameters:
29 | - numResults: Total number of results to be returned
30 |
31 | ### Usage Example: ###
32 | ```
33 | let resultCount = AutocompleteResultCount(numResults: 10)
34 | ```
35 | */
36 | public init(numResults: Int) {
37 | self.numResults = numResults
38 | self.numResultsForSection = nil
39 | }
40 |
41 | /**
42 | Create a result count object with a set number of results to be returned overall
43 |
44 | - Parameters:
45 | - numResultsForSection: Number of results to be returned per section
46 |
47 | ### Usage Example: ###
48 | ```
49 | let resultCount = AutocompleteResultCount(numResultsForSection: ["Search Suggestions": 3, "Products": 4])
50 | ```
51 | */
52 | public init(numResultsForSection: [String: Int]) {
53 | self.numResultsForSection = numResultsForSection
54 | self.numResults = nil
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logging/CIOLogger.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOLogger.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol CIOLogger {
12 | func log(_ message: String)
13 | }
14 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logging/CIOPrintLogger.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOPrintLogger.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public class CIOPrintLogger: CIOLogger {
12 | public func log(_ message: String) {
13 | #if DEBUG
14 | print(message)
15 | #endif
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/ABTesting/CIOABTestCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOABTestCell.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating the AB test cell
13 | */
14 | public struct CIOABTestCell {
15 | /**
16 | The name of the test cell
17 | */
18 | let key: String
19 |
20 | /**
21 | The test cell value
22 | */
23 | let value: String
24 |
25 | /**
26 | Create a AB test cell object
27 |
28 | - Parameters:
29 | - key: The name of the test cell
30 | - value: The test cell value
31 |
32 | ```
33 | ### Usage Example: ###
34 | let testCell = CIOABTestCell(key: "search", value: "control")
35 | ```
36 | */
37 | public init(key: String, value: String) {
38 | self.key = key
39 | self.value = value
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/ClientID/ClientIDGenerator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ClientIDGenerator.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | class ClientIDGenerator: IDGenerator {
13 |
14 | init() {}
15 |
16 | func generateID() -> String? {
17 | return UIDevice.current.identifierForVendor?.uuidString
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/ClientID/IDGenerator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserIDGenerator.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol IDGenerator {
12 | func generateID() -> String?
13 | }
14 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/ClientID/Persistence/CIOClientIdLoader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOClientIdLoader.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | struct CIOClientIdLoader: ClientIdLoader {
12 |
13 | init() {}
14 |
15 | func loadClientId() -> String? {
16 | if let clientId = UserDefaults.standard.object(forKey: Constants.Session.clientId) as? String {
17 | return clientId
18 | } else if let clientId = DependencyContainer.sharedInstance.clientIDGenerator().generateID() {
19 | saveClientId(clientId)
20 | return clientId
21 | } else {
22 | let uuid = NSUUID().uuidString
23 | saveClientId(uuid)
24 | return uuid
25 | }
26 | }
27 |
28 | func saveClientId(_ clientId: String) {
29 | UserDefaults.standard.set(clientId, forKey: Constants.Session.clientId)
30 | }
31 |
32 | func clearClientId() {
33 | UserDefaults.standard.removeObject(forKey: Constants.Session.clientId)
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/ClientID/Persistence/ClientIdLoader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ClientIdLoader.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol ClientIdLoader {
12 |
13 | func loadClientId() -> String?
14 | func saveClientId(_ clientId: String)
15 |
16 | func clearClientId()
17 | }
18 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Highlighting/Attributes/BoldAttributesProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BoldAttributesProvider.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class BoldAttributesProvider: CIOHighlightingAttributesProvider {
12 |
13 | public var fontNormal: UIFont
14 | public var fontBold: UIFont
15 |
16 | public var colorNormal: UIColor
17 | public var colorBold: UIColor
18 |
19 | public init(fontNormal: UIFont, fontBold: UIFont, colorNormal: UIColor, colorBold: UIColor) {
20 | self.colorNormal = colorNormal
21 | self.colorBold = colorBold
22 | self.fontNormal = fontNormal
23 | self.fontBold = fontBold
24 | }
25 |
26 | public func defaultSubstringAttributes() -> [NSAttributedString.Key: Any] {
27 | return [NSAttributedString.Key.font: self.fontBold,
28 | NSAttributedString.Key.foregroundColor: self.colorBold]
29 | }
30 |
31 | public func highlightedSubstringAttributes() -> [NSAttributedString.Key: Any] {
32 | return [NSAttributedString.Key.font: self.fontNormal,
33 | NSAttributedString.Key.foregroundColor: self.colorNormal]
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Highlighting/Attributes/CIOHighlightingAttributesProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOHighlightingAttributesProvider.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Provides higlighting attributes.
13 | */
14 | public protocol CIOHighlightingAttributesProvider {
15 | /**
16 | Method called by the CIOHiglighter to get highlighting attributes for parts of the string that aren't matched in the search term.
17 |
18 | - returns: NSAttributeString attributes for unmatched parts of the search term.
19 | */
20 | func defaultSubstringAttributes() -> [NSAttributedString.Key: Any]
21 |
22 | /**
23 | Method called by the CIOHiglighter to get highlighting attributes for parts of the string that are matched in the search term.
24 |
25 | - returns: NSAttributeString attributes for matched parts of the search term.
26 | */
27 | func highlightedSubstringAttributes() -> [NSAttributedString.Key: Any]
28 | }
29 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Query/CIOQueryFilters.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchFilters.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public typealias Filter = (key: String, value: String)
12 |
13 | public struct CIOQueryFilters {
14 | public let groupFilter: String?
15 | public let facetFilters: [Filter]?
16 |
17 | public init(groupFilter: String?, facetFilters: [Filter]?) {
18 | self.groupFilter = groupFilter
19 | self.facetFilters = facetFilters
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Query/CIOQueryFmtOptions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOQueryFmtOptions.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public typealias FmtOption = (key: String, value: String)
12 |
13 | public struct CIOQueryFmtOptions {
14 | public let fmtOptions: [FmtOption]?
15 |
16 | public init(fmtOptions: [FmtOption]?) {
17 | self.fmtOptions = fmtOptions
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Request/Builder/CIOBrowseFacetOptionsQueryBuilder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOBrowseFacetOptionsQueryBuilder.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Request builder for creating an browse facet options query.
13 | */
14 | public class CIOBrowseFacetOptionsQueryBuilder {
15 |
16 | /**
17 | The name of the facet whose options to return
18 | */
19 | var facetName: String
20 |
21 | /**
22 | Whether or not to return hidden facets
23 | */
24 | var showHiddenFacets: Bool?
25 |
26 | /**
27 | Create a Browse facet options request query builder
28 | */
29 | public init(facetName: String) {
30 | self.facetName = facetName
31 | }
32 |
33 | /**
34 | Add a bool indicating whether or not to return hidden facets
35 | */
36 | public func setShowHiddenFacets(_ showHiddenFacets: Bool) -> CIOBrowseFacetOptionsQueryBuilder {
37 | self.showHiddenFacets = showHiddenFacets
38 | return self
39 | }
40 |
41 | /**
42 | Build the request object set all of the provided data
43 |
44 | ### Usage Example: ###
45 | ```
46 | let query = CIOBrowseFacetOptionsQueryBuilder(facetName: "price")
47 | .setShowHiddenFacets(true)
48 | .build()
49 |
50 | constructor.browseFacetOptions(forQuery: query, completionHandler: { ... })
51 | ```
52 | */
53 | public func build() -> CIOBrowseFacetOptionsQuery {
54 | return CIOBrowseFacetOptionsQuery(facetName: facetName, showHiddenFacets: showHiddenFacets)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Request/CIOBrowseFacetOptionsQuery.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOBrowseFacetOptionsQuery.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating the necessary and additional parameters required to execute a browse facet options query.
13 | */
14 | public struct CIOBrowseFacetOptionsQuery: CIORequestData {
15 | /**
16 | Name of the facet whose options to return
17 | */
18 | public let facetName: String
19 |
20 | /**
21 | Whether or not to return hidden facets
22 | */
23 | public let showHiddenFacets: Bool?
24 |
25 | func url(with baseURL: String) -> String {
26 | return String(format: Constants.BrowseFacetOptionsQuery.format, baseURL)
27 | }
28 |
29 | /**
30 | Create a Browse facet options request query object
31 |
32 | - Parameters:
33 | - facetName: Name of the facet whose options to return
34 | - showHiddenFacets: Whether or not to return hidden facets
35 |
36 | ### Usage Example: ###
37 | ```
38 | let browseFacetsQuery = CIOBrowseFacetOptionsQuery(facetName: "price", showHiddenFacets: true)
39 | ```
40 | */
41 | public init(facetName: String, showHiddenFacets: Bool? = nil) {
42 | self.facetName = facetName
43 | self.showHiddenFacets = showHiddenFacets
44 | }
45 |
46 | func decorateRequest(requestBuilder: RequestBuilder) {
47 | requestBuilder.set(facetName: self.facetName)
48 |
49 | if self.showHiddenFacets != nil {
50 | requestBuilder.set(showHiddenFacets: self.showHiddenFacets!)
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Request/CIOGroupsSortOption.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOGroupsSortOption.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a group sort option
13 | */
14 | public struct CIOGroupsSortOption {
15 | /**
16 | The sort method ("relevance", "value", or "num_matches")
17 | */
18 | public let sortBy: CIOGroupsSortBy
19 |
20 | /**
21 | The sort order (i.e. "ascending" or "descending")
22 | */
23 | public let sortOrder: CIOGroupsSortOrder
24 |
25 | /**
26 | Create a groups sort option
27 |
28 | - parameters
29 | - sortBy: The sort method ("relevance", "value", or "num_matches")
30 | - sortOrder: The sort order (i.e. "ascending" or "descending"
31 | */
32 | public init(sortBy: CIOGroupsSortBy, sortOrder: CIOGroupsSortOrder) {
33 | self.sortBy = sortBy
34 | self.sortOrder = sortOrder
35 | }
36 |
37 | public enum CIOGroupsSortBy: String {
38 | case relevance
39 | case value
40 | case num_matches
41 | }
42 |
43 | public enum CIOGroupsSortOrder: String {
44 | case ascending
45 | case descending
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Request/CIOItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOItem.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public struct CIOItem {
12 | var customerID: String
13 | var variationID: String?
14 | var quantity: Int?
15 |
16 | public init(customerID: String, variationID: String? = nil, quantity: Int? = nil) {
17 | self.customerID = customerID
18 | self.variationID = variationID
19 | self.quantity = quantity
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Request/CIORequestData.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIORequestData.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol CIORequestData {
12 |
13 | func decorateRequest(requestBuilder: RequestBuilder)
14 |
15 | func url(with baseURL: String) -> String
16 |
17 | func urlWithFormat(baseURL: String, format: String) -> String
18 |
19 | func queryItems(baseItems: [URLQueryItem]) -> [URLQueryItem]
20 |
21 | func httpMethod() -> String
22 |
23 | func httpBody(baseParams: [String: Any]) -> Data?
24 | }
25 |
26 | extension CIORequestData {
27 | // default httpMethod is GET
28 | func httpMethod() -> String {
29 | return "GET"
30 | }
31 |
32 | // default body is null
33 | func httpBody(baseParams: [String: Any]) -> Data? {
34 | return nil
35 | }
36 |
37 | // default query items is all of them
38 | func queryItems(baseItems: [URLQueryItem]) -> [URLQueryItem] {
39 | return baseItems
40 | }
41 |
42 | // default to empty string
43 | func urlWithFormat(baseURL: String, format: String) -> String {
44 | return ""
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Request/CIOTrackInputFocusData.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOTrackInputFocusData.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating the parameters that must/can be set set in order to track search bar focus
13 | */
14 | struct CIOTrackInputFocusData: CIORequestData {
15 | let searchTerm: String?
16 |
17 | func url(with baseURL: String) -> String {
18 | return String(format: Constants.TrackInputFocus.format, baseURL)
19 | }
20 |
21 | init(searchTerm: String?) {
22 | self.searchTerm = searchTerm
23 | }
24 |
25 | func decorateRequest(requestBuilder: RequestBuilder) {
26 | if let term = self.searchTerm {
27 | requestBuilder.set(searchTerm: term)
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Request/CIOTrackSearchResultClickData.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOTrackSearchResultClickData.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating the parameters that must/can be set set in order to track search result click
13 | */
14 | struct CIOTrackSearchResultClickData: CIORequestData {
15 | let searchTerm: String
16 | let itemName: String
17 | let customerID: String
18 | var sectionName: String?
19 | let resultID: String?
20 | let variationID: String?
21 |
22 | func url(with baseURL: String) -> String {
23 | return String(format: Constants.TrackSearchResultClick.format, baseURL, self.searchTerm.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!)
24 | }
25 |
26 | init(searchTerm: String, itemName: String, customerID: String, sectionName: String? = nil, resultID: String? = nil, variationID: String? = nil) {
27 | self.searchTerm = searchTerm
28 | self.itemName = itemName
29 | self.customerID = customerID
30 | self.sectionName = sectionName
31 | self.resultID = resultID
32 | self.variationID = variationID
33 | }
34 |
35 | func decorateRequest(requestBuilder: RequestBuilder) {
36 | requestBuilder.set(name: self.itemName)
37 | requestBuilder.set(customerID: self.customerID)
38 | requestBuilder.set(autocompleteSection: self.sectionName)
39 | requestBuilder.set(resultID: self.resultID)
40 | requestBuilder.set(variationID: self.variationID)
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Request/CIOTrackSearchSubmitData.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOTrackSearchSubmitData.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating the parameters that must/can be set in order to track a search submission
13 | */
14 | struct CIOTrackSearchSubmitData: CIORequestData {
15 |
16 | let searchTerm: String
17 | let originalQuery: String
18 | let group: CIOGroup?
19 |
20 | func url(with baseURL: String) -> String {
21 | return String(format: Constants.TrackSearchSubmit.format, baseURL, self.searchTerm.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!)
22 | }
23 |
24 | init(searchTerm: String, originalQuery: String, group: CIOGroup? = nil) {
25 | self.searchTerm = searchTerm
26 | self.originalQuery = originalQuery
27 | self.group = group
28 | }
29 |
30 | func decorateRequest(requestBuilder: RequestBuilder) {
31 | requestBuilder.set(originalQuery: self.originalQuery)
32 | if let group = self.group {
33 | requestBuilder.set(groupName: group.displayName)
34 | requestBuilder.set(groupID: group.groupID)
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Request/CIOTrackSessionStartData.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOTrackSessionStartData.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating the parameters that must/can be set set in order to track session start
13 | */
14 | struct CIOTrackSessionStartData: CIORequestData {
15 | let session: Int
16 |
17 | func url(with baseURL: String) -> String {
18 | return String(format: Constants.TrackSessionStart.format, baseURL)
19 | }
20 |
21 | init(session: Int) {
22 | self.session = session
23 | }
24 |
25 | func decorateRequest(requestBuilder: RequestBuilder) {
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOAutocompleteResult.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOAutocompleteResult.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 | import Foundation
9 |
10 | /**
11 | Defines an autocomplete item in the list. Since you can search for a term in a group, this class holds
12 | both the result and the group to search in.
13 | */
14 |
15 | @objc
16 | public class CIOAutocompleteResult: NSObject {
17 | /**
18 | Result returned for the query
19 | */
20 | public let result: CIOResult
21 |
22 | /**
23 | Group (or category) the result belongs to
24 | */
25 | public let group: CIOGroup?
26 |
27 | /**
28 | Create a autocomplete result
29 |
30 | - Parameters:
31 | - result: Result info
32 | - group: Group info
33 | */
34 | public init(result: CIOResult, group: CIOGroup? = nil) {
35 | self.result = result
36 | self.group = group
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOCollectionData.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOCollectionData.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 | import Foundation
9 |
10 | /**
11 | Struct encapsulating a collection
12 | */
13 | public class CIOCollectionData: NSObject {
14 | /**
15 | Id of the collection
16 | */
17 | public let id: String
18 |
19 | /**
20 | Display name of the collection
21 | */
22 | public let display_name: String
23 |
24 | /**
25 | Additional metadata for the collection
26 | */
27 | public let data: [String: Any]
28 |
29 | /**
30 | Create a collection object
31 |
32 | - Parameters:
33 | - json: JSON data from server reponse
34 | */
35 | init?(json: JSONObject?) {
36 | guard let json = json, let id = json["id"] as? String, let display_name = json["display_name"] as? String else {
37 | return nil
38 | }
39 |
40 | let data = json["data"] as? [String: Any] ?? [:]
41 |
42 | self.id = id
43 | self.display_name = display_name
44 | self.data = data
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOGroup.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOGroup.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a group
13 | */
14 | @objc
15 | public class CIOGroup: NSObject {
16 | /**
17 | Display name of the group (or category)
18 | */
19 | public let displayName: String
20 |
21 | /**
22 | Group ID
23 | */
24 | public let groupID: String
25 |
26 | /**
27 | The full path of the group hierarchy
28 | */
29 | public let path: String?
30 |
31 | /**
32 | Create a group
33 |
34 | - Parameters:
35 | - displayName: Display nam eof the group
36 | - groupID: Group ID
37 | - path: The full path of the group hierarchy
38 | */
39 | public init(displayName: String, groupID: String, path: String?) {
40 | self.displayName = displayName
41 | self.groupID = groupID
42 | self.path = path
43 | }
44 |
45 | /**
46 | Create a group (from JSON)
47 |
48 | - Parameters:
49 | - json: JSON data from the server response
50 | */
51 | init?(json: JSONObject) {
52 | guard let name = json["display_name"] as? String else { return nil }
53 | guard let groupID = json["group_id"] as? String else { return nil }
54 |
55 | self.displayName = name
56 | self.groupID = groupID
57 | self.path = json["path"] as? String
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOQuizImages.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOQuestionImages.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a question images
13 | */
14 | public struct CIOQuizImages {
15 | /**
16 | Primary image URL
17 | */
18 | public let primaryUrl: String?
19 |
20 | /**
21 | Primary image alternative text
22 | */
23 | public let primaryAlt: String?
24 |
25 | /**
26 | Secondary image URL
27 | */
28 | public let secondaryUrl: String?
29 |
30 | /**
31 | Secondary image alternative text
32 | */
33 | public let secondaryAlt: String?
34 | }
35 |
36 | /**
37 | Define a question images
38 | */
39 | public extension CIOQuizImages {
40 | /**
41 | Create a question images
42 |
43 | - Parameters:
44 | - json: JSON data from the server response
45 | */
46 | init?(json: JSONObject) {
47 | if let primaryUrl = json["primary_url"] as? String { self.primaryUrl = primaryUrl } else { self.primaryUrl = nil }
48 | if let primaryAlt = json["primary_alt"] as? String { self.primaryAlt = primaryAlt } else { self.primaryAlt = nil }
49 | if let secondaryUrl = json["secondary_url"] as? String { self.secondaryUrl = secondaryUrl } else { self.secondaryUrl = nil }
50 | if let secondaryAlt = json["secondary_alt"] as? String { self.secondaryAlt = secondaryAlt } else { self.secondaryAlt = nil }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOQuizOption.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOQuizOption.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a quiz option
13 | */
14 | public struct CIOQuizOption {
15 | /**
16 | The id of the option
17 | */
18 | public let id: Int
19 |
20 | /**
21 | The value of the option
22 | */
23 | public let value: String
24 |
25 | /**
26 | The attribute associated with the option
27 | */
28 | public let attribute: CIOQuizOptionAttribute?
29 |
30 | /**
31 | The images associated with the option
32 | */
33 | public let images: CIOQuizImages?
34 | }
35 |
36 | /**
37 | Define a quiz option
38 | */
39 | public extension CIOQuizOption {
40 | /**
41 | Create a quiz option
42 |
43 | - Parameters:
44 | - json: JSON data from the server response
45 | */
46 | init?(json: JSONObject) {
47 | guard let id = json["id"] as? Int else { return nil }
48 | guard let value = json["value"] as? String else { return nil }
49 |
50 | if let attribute = json["attribute"] as? JSONObject {
51 | self.attribute = CIOQuizOptionAttribute(json: attribute)
52 | } else {
53 | self.attribute = CIOQuizOptionAttribute(json: [String: Any]())
54 | }
55 |
56 | if let images = json["images"] as? JSONObject {
57 | self.images = CIOQuizImages(json: images)
58 | } else {
59 | self.images = CIOQuizImages(json: [String: Any]())
60 | }
61 |
62 | self.id = id
63 | self.value = value
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOQuizOptionAttribute.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOQuizOptionAttribute.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a quiz option attribute
13 | */
14 | public struct CIOQuizOptionAttribute {
15 | /**
16 | Quiz option attribute name
17 | */
18 | public let name: String
19 |
20 | /**
21 | Quiz option attribute value
22 | */
23 | public let value: String
24 | }
25 |
26 | /**
27 | Define a quiz option attribute
28 | */
29 | public extension CIOQuizOptionAttribute {
30 | /**
31 | Create a quiz option attribute object
32 |
33 | - Parameters:
34 | - json: JSON data from the server response
35 | */
36 | init?(json: JSONObject) {
37 | guard let name = json["name"] as? String else { return nil }
38 | guard let value = json["value"] as? String else { return nil }
39 |
40 | self.name = name
41 | self.value = value
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOQuizResult.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOQuizResultsData.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a result data object with additional information about the result
13 | */
14 | public struct CIOQuizResult {
15 | /**
16 | Filter Expressions
17 | */
18 | public let filterExpressions: [String: Any]
19 |
20 | /**
21 | Results Url
22 | */
23 | public let resultsUrl: String
24 | }
25 |
26 | public extension CIOQuizResult {
27 | /**
28 | Create a result data object
29 | - Parameters:
30 | - json: JSON data from the server response
31 | */
32 | init?(json: JSONObject) {
33 | let filterExpressions = json["filter_expression"] as? [String: Any] ?? [:]
34 | let resultsUrl = json["results_url"] as? String ?? ""
35 |
36 | self.filterExpressions = filterExpressions
37 | self.resultsUrl = resultsUrl
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIORecommendationsPod.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIORecommendationsPod.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a recommendations pod
13 | */
14 | public struct CIORecommendationsPod {
15 | public let displayName: String
16 | public let id: String
17 | }
18 |
19 | /**
20 | Define a recommendations opd
21 | */
22 | public extension CIORecommendationsPod {
23 | /**
24 | Create a recommendations pod
25 |
26 | - Parameters:
27 | - json: JSON data from the server response
28 | */
29 | init?(json: JSONObject) {
30 | guard let displayName = json["display_name"] as? String else { return nil }
31 | guard let id = json["id"] as? String else { return nil }
32 |
33 | self.displayName = displayName
34 | self.id = id
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIORecommendationsStrategy.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIORecommendationsStrategy.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating the recommendations strategy
13 | */
14 | public struct CIORecommendationsStrategy {
15 | /**
16 | The id of the strategy
17 | */
18 | public let id: String
19 | }
20 |
21 | public extension CIORecommendationsStrategy {
22 |
23 | /**
24 | Create a recommendations strategy object
25 |
26 | - Parameters:
27 | - json: JSON data from the server response
28 | */
29 | init?(json: JSONObject) {
30 | let id = json["id"] as? String ?? ""
31 |
32 | self.id = id
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIORefinedContent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIORefinedContent.swift
3 | // ConstructorAutocomplete
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a refined content with associated metadata
13 | */
14 | public struct CIORefinedContent {
15 | /**
16 | Refine dcontent data
17 | */
18 | public let data: [String: Any]
19 |
20 | /**
21 | Create a refined content object
22 |
23 | - Parameters:
24 | - json: JSON data from server reponse
25 | */
26 | public init?(json: JSONObject) {
27 | guard let data = json["data"] as? [String: Any] else { return nil }
28 |
29 | self.data = data
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOResultFacet.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOResultFacet.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a result facet
13 | */
14 | public struct CIOResultFacet {
15 | /**
16 | The name of the facet
17 | */
18 | public let name: String
19 |
20 | /**
21 | List of facet option values
22 | */
23 | public let values: [String]
24 |
25 | /**
26 | Create a result facet
27 |
28 | - Parameters:
29 | - json: JSON data from the server response
30 | */
31 | public init?(json: JSONObject) {
32 | guard let name = json["name"] as? String else { return nil }
33 |
34 | self.name = name
35 | self.values = json["values"] as? [String] ?? []
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOResultSourceData.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOResultSourcesData.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 | import Foundation
9 |
10 | /**
11 | Struct encapsulating a result source data
12 | */
13 | public class CIOResultSourceData: NSObject {
14 | /**
15 | Number of results matching
16 | */
17 | public let count: Int
18 |
19 | /**
20 | Create a result source object
21 |
22 | - Parameters:
23 | - json: JSON data from server reponse
24 | */
25 | init?(json: JSONObject?) {
26 | guard let json = json, let count = json["count"] as? Int else {
27 | return nil
28 | }
29 |
30 | self.count = count
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOResultSources.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOResultSources.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 | import Foundation
9 |
10 | /**
11 | Struct encapsulating a result source
12 | */
13 | public class CIOResultSources: NSObject {
14 | /**
15 | Number of token match results
16 | */
17 | public let tokenMatch: CIOResultSourceData
18 |
19 | /**
20 | Number of embedding match results
21 | */
22 | public let embeddingsMatch: CIOResultSourceData
23 |
24 | /**
25 | Create a result sources object
26 |
27 | - Parameters:
28 | - json: JSON data from server reponse
29 | */
30 | init?(json: JSONObject?) {
31 | guard let json = json,
32 | let tokenMatchJson = json["token_match"] as? JSONObject,
33 | let embeddingsMatchJson = json["embeddings_match"] as? JSONObject,
34 | let tokenMatchData = CIOResultSourceData(json: tokenMatchJson),
35 | let embeddingsMatchData = CIOResultSourceData(json: embeddingsMatchJson) else {
36 | return nil
37 | }
38 |
39 | self.tokenMatch = tokenMatchData
40 | self.embeddingsMatch = embeddingsMatchData
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOSearchRedirectInfo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOSearchRedirectInfo.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating the Search redirect info
13 | */
14 | public struct CIOSearchRedirectInfo {
15 | /**
16 | The redirect URL
17 | */
18 | public let url: String
19 |
20 | /**
21 | Match ID
22 | */
23 | public let matchID: Int
24 |
25 | /**
26 | Rule ID
27 | */
28 | public let ruleID: Int
29 | }
30 |
31 | public extension CIOSearchRedirectInfo {
32 | /**
33 | Create a Search redirect info object
34 |
35 | - Parameters:
36 | - object: JSON Object
37 | */
38 | init?(object: JSONObject?) {
39 | guard let json = object else { return nil }
40 | guard let data = json["data"] as? JSONObject else { return nil }
41 | guard let url = data["url"] as? String else { return nil }
42 | guard let matchID = data["match_id"] as? Int else { return nil }
43 | guard let ruleID = data["rule_id"] as? Int else { return nil }
44 |
45 | self.url = url
46 | self.matchID = matchID
47 | self.ruleID = ruleID
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/CIOSortOption.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SortOption.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct encapsulating a sort option
13 | */
14 | public struct CIOSortOption {
15 | /**
16 | Display name of the sort option
17 | */
18 | public let displayName: String
19 |
20 | /**
21 | The field to sort by
22 | */
23 | public let sortBy: String
24 |
25 | /**
26 | The sort order (i.e. "ascending" or "descending")
27 | */
28 | public let sortOrder: CIOSortOrder
29 |
30 | /**
31 | The status of the sort option (i.e. "selected")
32 | */
33 | public let status: String
34 | }
35 |
36 | public extension CIOSortOption {
37 | /**
38 | Create a sort option
39 |
40 | - parameters
41 | - json: JSON data from the server response
42 | */
43 | init?(json: JSONObject) {
44 | guard let displayName = json["display_name"] as? String else { return nil }
45 | guard let sortOrderStr = json["sort_order"] as? String else { return nil }
46 | guard let sortOrder = CIOSortOrder(rawValue: sortOrderStr) else { return nil }
47 | guard let sortBy = json["sort_by"] as? String else { return nil }
48 | guard let status = json["status"] as? String else { return nil }
49 |
50 | self.displayName = displayName
51 | self.sortBy = sortBy
52 | self.sortOrder = sortOrder
53 | self.status = status
54 | }
55 | }
56 |
57 | public enum CIOSortOrder: String {
58 | case ascending
59 | case descending
60 | }
61 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/Responses/CIOAutocompleteResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOAutocompleteResponse.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public typealias JSONObject = [String: Any]
12 |
13 | /**
14 | Struct representing the autocomplete data response from the server.
15 | */
16 | public struct CIOAutocompleteResponse {
17 | /**
18 | List of results broken down by sections
19 | */
20 | public let sections: [String: [CIOAutocompleteResult]]
21 |
22 | /**
23 | Additional information about the request and result ID
24 | */
25 | public let json: JSONObject
26 |
27 | /**
28 | Request object used to retrieve the Autocomplete Response
29 | */
30 | public var request: JSONObject
31 |
32 | public init(sections: [String: [CIOAutocompleteResult]], json: JSONObject, request: JSONObject = [:]) {
33 | self.sections = sections
34 | self.json = json
35 | self.request = request
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/Responses/CIOBrowseFacetOptionsResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOBrowseFacetOptionsResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct representing the browse facet options data response from the server.
13 | */
14 | public struct CIOBrowseFacetOptionsResponse {
15 | /**
16 | List of facets returned
17 | */
18 | public let facets: [CIOFilterFacet]
19 |
20 | /**
21 | Result ID of the result set returned
22 | */
23 | public let resultID: String
24 | }
25 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/Responses/CIOBrowseFacetsResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOBrowseFacetsResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct representing the browse facets data response from the server.
13 | */
14 | public struct CIOBrowseFacetsResponse {
15 | /**
16 | List of facets returned
17 | */
18 | public let facets: [CIOFilterFacet]
19 |
20 | /**
21 | Total number of results for the query
22 | */
23 | public let totalNumResults: Int
24 |
25 | /**
26 | Result ID of the result set returned
27 | */
28 | public let resultID: String
29 | }
30 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/Responses/CIOBrowseResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOBrowseResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct representing the browse data response from the server.
13 | */
14 | public struct CIOBrowseResponse {
15 | /**
16 | List of facets returned for the result set
17 | */
18 | public let facets: [CIOFilterFacet]
19 |
20 | /**
21 | List of groups (categories) returned for the result set
22 | */
23 | public let groups: [CIOFilterGroup]
24 |
25 | /**
26 | List of results returned for the browse query
27 | */
28 | public let results: [CIOResult]
29 |
30 | /**
31 | List of sorting options
32 | */
33 | public let sortOptions: [CIOSortOption]
34 |
35 | /**
36 | Total number of results for the query
37 | */
38 | public let totalNumResults: Int
39 |
40 | /**
41 | Result ID of the result set returned
42 | */
43 | public let resultID: String
44 |
45 | /**
46 | Collection of the result if browsing collection_id
47 | */
48 | public let collection: CIOCollectionData?
49 |
50 | /**
51 | A list of refined content
52 | */
53 | public let refinedContent: [CIORefinedContent]
54 |
55 | /**
56 | Sources of the result set
57 | */
58 | public let resultSources: CIOResultSources?
59 |
60 | /**
61 | Request object used to retrieve the Browse Response
62 | */
63 | public var request: JSONObject
64 | }
65 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/Responses/CIOQuizQuestionResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOQuizQuestionResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct representing the quiz question response from the server.
13 | */
14 | public struct CIOQuizQuestionResponse {
15 | /**
16 | Next question in the quiz
17 | */
18 | public let nextQuestion: CIOQuizQuestion
19 |
20 | /**
21 | Unique quiz_version_id for the quiz.
22 | The quiz version id will be returned with the first request and it should be passed with subsequent requests.
23 | More information can be found: https://docs.constructor.com/reference/configuration-quizzes
24 | */
25 | public let quizVersionID: String
26 |
27 | /**
28 | Unique quiz_session_id for the quiz.
29 | The quiz session id will be returned with the first request and it should be passed with subsequent requests.
30 | More information can be found: https://docs.constructor.com/reference/configuration-quizzes
31 | */
32 | public let quizSessionID: String
33 |
34 | /**
35 | Id of the quiz
36 | */
37 | public let quizID: String
38 | }
39 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Result/Responses/CIORecommendationsResponse.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIORecommendationsResponse.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | Struct representing the recommendations data response from the server.
13 | */
14 | public struct CIORecommendationsResponse {
15 | /**
16 | Pod information
17 | */
18 | public let pod: CIORecommendationsPod
19 |
20 | /**
21 | List of results returned for the recommendations query
22 | */
23 | public let results: [CIOResult]
24 |
25 | /**
26 | Total number of results for the query
27 | */
28 | public let totalNumResults: Int
29 |
30 | /**
31 | Result ID of the result set returned
32 | */
33 | public let resultID: String
34 |
35 | /**
36 | Request object used to retrieve the Recommendations Response
37 | */
38 | public var request: JSONObject
39 | }
40 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Session/CIOSessionManagerDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOSessionManagerDelegate.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol CIOSessionManagerDelegate: AnyObject {
12 | func sessionDidChange(from: Int, to: Int)
13 | }
14 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Session/Date/CurrentTimeDateProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CurrentTimeDateProvider.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | struct CurrentTimeDateProvider: DateProvider {
12 |
13 | init() {}
14 |
15 | func provideDate() -> Date {
16 | return Date()
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Session/Date/DateProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DateProvider.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol DateProvider {
12 | func provideDate() -> Date
13 | }
14 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Session/Persistence/CIOSessionLoader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOSessionLoader.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | struct CIOSessionLoader: SessionLoader {
12 |
13 | init() {}
14 |
15 | func loadSession() -> Session? {
16 | if let data = UserDefaults.standard.object(forKey: Constants.Session.key) as? Data {
17 | return NSKeyedUnarchiver.unarchiveObject(with: data) as? Session
18 | } else {
19 | return nil
20 | }
21 | }
22 |
23 | func saveSession(_ session: Session) {
24 | let data = NSKeyedArchiver.archivedData(withRootObject: session)
25 | UserDefaults.standard.set(data, forKey: Constants.Session.key)
26 | }
27 |
28 | func clearSession() {
29 | UserDefaults.standard.removeObject(forKey: Constants.Session.key)
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Session/Persistence/SessionLoader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SessionLoader.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol SessionLoader {
12 |
13 | func loadSession() -> Session?
14 | func saveSession(_ session: Session)
15 |
16 | func clearSession()
17 | }
18 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Session/Session.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Session.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public class Session: NSObject, NSCoding {
12 | public var id: Int
13 | public let createdAt: TimeInterval
14 |
15 | public init(id: Int, createdAt: TimeInterval) {
16 | self.id = id
17 | self.createdAt = createdAt
18 | }
19 |
20 | public required init?(coder aDecoder: NSCoder) {
21 | self.id = aDecoder.decodeInteger(forKey: Constants.Session.id)
22 | self.createdAt = aDecoder.decodeDouble(forKey: Constants.Session.createdAt)
23 | }
24 |
25 | public func encode(with aCoder: NSCoder) {
26 | aCoder.encode(self.id, forKey: Constants.Session.id)
27 | aCoder.encode(self.createdAt, forKey: Constants.Session.createdAt)
28 | }
29 |
30 | public func setSessionID(sessionID: Int) {
31 | self.id = sessionID
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/Logic/Session/SessionManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SessionManager.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol SessionManager: AnyObject {
12 | var delegate: CIOSessionManagerDelegate? { get set }
13 |
14 | func getSessionWithIncrement() -> Int
15 | func getSessionWithoutIncrement() -> Int
16 |
17 | func setSessionID(id: Int)
18 |
19 | func setup()
20 | }
21 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/CustomCell/SearchResultCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOAutocompleteCell.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol CIOAutocompleteCell {
12 | func setup(result: CIOAutocompleteResult, searchTerm: String, highlighter: CIOHighlighter)
13 | }
14 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/DefaultSearchItemCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultSearchItemCell.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class DefaultSearchItemCell: UITableViewCell, CIOAutocompleteCell {
12 |
13 | @IBOutlet public weak var labelText: UILabel!
14 |
15 | override public func awakeFromNib() {
16 | super.awakeFromNib()
17 | }
18 |
19 | public func setup(result: CIOAutocompleteResult, searchTerm: String, highlighter: CIOHighlighter) {
20 | if let group = result.group {
21 | let groupString = NSMutableAttributedString()
22 |
23 | groupString.append(highlighter.highlight(searchTerm: searchTerm, itemTitle: result.result.value))
24 |
25 | let fontGroup = Constants.UI.Font.defaultFontNormal.withSize(11)
26 | let groupAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: fontGroup,
27 | NSAttributedString.Key.foregroundColor: Constants.UI.Color.defaultFontColorNormal]
28 |
29 | groupString.append(NSAttributedString.build(string: "\nin \(group.displayName)", attributes: groupAttributes))
30 | self.labelText.attributedText = groupString
31 | } else {
32 | self.labelText.attributedText = highlighter.highlight(searchTerm: searchTerm, itemTitle: result.result.value)
33 | }
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/Empty/EmptyScreenView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EmptyScreenView.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class EmptyScreenView: UIView {
12 |
13 | override public func awakeFromNib() {
14 | super.awakeFromNib()
15 | self.backgroundColor = CIOStyle.colorLightGrey()
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/Error/CIOErrorView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOErrorView.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | /**
12 | Conform to this protocol if you want to use a custom error view.
13 | */
14 | public protocol CIOErrorView: NSObjectProtocol {
15 | /**
16 | Returns a UIView instance. If your UIView implements this protocol, simply return self.
17 |
18 | - returns: UIView to be added to the view hierarchy if an error occurs.
19 | */
20 | func asView() -> UIView
21 |
22 | /**
23 | Method called when if an error occurs.
24 |
25 | - parameter errorString: String value of an error that occurred.
26 | */
27 | func setErrorString(errorString: String)
28 | }
29 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/SearchBar/CIOSearchBarDisplayMode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOSearchBarDisplayMode.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public enum CIOSearchBarDisplayMode {
12 | case tableViewHeader
13 | case navigationBar
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/SearchBar/CustomSearchBar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomSearchBar.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class CustomSearchBar: UISearchBar {
12 |
13 | public var shouldShowCancelButton = false
14 |
15 | public init() {
16 | super.init(frame: .zero)
17 | }
18 |
19 | public override init(frame: CGRect) {
20 | super.init(frame: frame)
21 | }
22 |
23 | public required init?(coder aDecoder: NSCoder) {
24 | super.init(coder: aDecoder)
25 | }
26 |
27 | override public func setShowsCancelButton(_ showsCancelButton: Bool, animated: Bool) {
28 | super.setShowsCancelButton(self.shouldShowCancelButton && self.isFirstResponder, animated: animated)
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/SearchBar/CustomSearchController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomSearchController.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class CustomSearchController: UISearchController {
12 |
13 | @objc lazy var searchBarPvt: CustomSearchBar = {
14 | [unowned self] in
15 | let customSearchBar = CustomSearchBar(frame: CGRect.zero)
16 | return customSearchBar
17 | }()
18 |
19 | override public var searchBar: UISearchBar {
20 | get {
21 | return searchBarPvt
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/Style/CIOStyle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOStyle.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public class CIOStyle {
12 |
13 | class func colorLightGrey() -> UIColor {
14 | let val = 245
15 | return UIColor.RGB(val, green: val, blue: val)
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/ViewModel/AbstractAutocompleteViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AbstractAutocompleteViewModel.swift
3 | // AutocompleteClient
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol AbstractAutocompleteViewModel {
12 |
13 | var results: [AutocompleteViewModelSection] { get set }
14 | var delegate: AutocompleteViewModelDelegate? { get set }
15 | var screenTitle: String { get set }
16 | var modelSorter: (String, String) -> Bool { get set }
17 | var searchTerm: String { get }
18 |
19 | func set(searchResult: AutocompleteResult, completionHandler: @escaping () -> Void)
20 |
21 | func getResult(atIndexPath indexPath: IndexPath) -> CIOAutocompleteResult
22 | func getSectionName(atIndex index: Int) -> String
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/ViewModel/AutocompleteResult.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteResult.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public class AutocompleteResult {
12 | public let query: CIOAutocompleteQuery
13 | public var response: CIOAutocompleteResponse?
14 | public let timestamp: TimeInterval
15 |
16 | public init(query: CIOAutocompleteQuery, timestamp: TimeInterval = Date().timeIntervalSince1970) {
17 | self.query = query
18 | self.timestamp = timestamp
19 | }
20 |
21 | public func isInitiatedAfter(result: AutocompleteResult) -> Bool {
22 | return self.timestamp > result.timestamp
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/ViewModel/AutocompleteViewModelDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteViewModelDelegate.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol AutocompleteViewModelDelegate: AnyObject {
12 | func viewModel(_ viewModel: AbstractAutocompleteViewModel, didIgnoreResult result: AutocompleteResult)
13 | func viewModel(_ viewModel: AbstractAutocompleteViewModel, didSetResult result: AutocompleteResult)
14 | }
15 |
--------------------------------------------------------------------------------
/AutocompleteClient/FW/UI/ViewModel/AutocompleteViewModelSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteViewModelSection.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | public struct AutocompleteViewModelSection {
12 | public let items: [CIOAutocompleteResult]
13 | public let sectionName: String
14 |
15 | public init(items: [CIOAutocompleteResult], sectionName: String) {
16 | self.items = items
17 | self.sectionName = sectionName
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/AutocompleteClient/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 4.1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/AutocompleteClient/Resources/constructor-io-error-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/AutocompleteClient/Resources/constructor-io-error-icon.png
--------------------------------------------------------------------------------
/AutocompleteClient/Resources/constructor-io-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/AutocompleteClient/Resources/constructor-io-logo.png
--------------------------------------------------------------------------------
/AutocompleteClient/Utils/Collection/Collection+MapKeys.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Collection+MapKeys.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | extension Dictionary {
12 | func mapKeys(_ mapping: (_ key: Key) -> T) -> [T: Value] {
13 | var newDictionary: [T: Value] = [:]
14 | for (key, value) in self {
15 | newDictionary[mapping(key)] = value
16 | }
17 |
18 | return newDictionary
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/AutocompleteClient/Utils/Color/UIColor+RGB.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+RGB.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | class func RGB(_ red: Int, green: Int, blue: Int) -> UIColor {
13 | return self.RGBA(red, green: green, blue: blue, alpha: 255)
14 | }
15 |
16 | class func RGBA(_ red: Int, green: Int, blue: Int, alpha: CGFloat) -> UIColor {
17 | return UIColor(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: alpha)
18 | }
19 |
20 | class func hex(rgb: Int) -> UIColor {
21 | return self.RGB((rgb >> 16) & 0xFF, green: (rgb >> 8) & 0xFF, blue: rgb & 0xFF)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/AutocompleteClient/Utils/String/NSAttributedString+Build.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NSAttributedString+Build.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | extension NSAttributedString {
12 |
13 | static func build(string: String, attributes: [NSAttributedString.Key: Any]) -> NSAttributedString {
14 | return NSAttributedString(string: string, attributes: attributes)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/AutocompleteClient/Utils/String/String+SearchSuggestionsSection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+SearchSuggestionsSection.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | extension String {
12 | func isSearchSuggestionString() -> Bool {
13 | return self.lowercased().replacingOccurrences(of: " ", with: "") == "searchsuggestions"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AutocompleteClient/Utils/String/String+Trim.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+Trim.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | extension String {
12 | func trim() -> String {
13 | return self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AutocompleteClient/Utils/UI/UISearchBar+TextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UISearchBar+TextField.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | public extension UISearchBar {
12 | func searchTextField() -> UITextField? {
13 | return self.findSubview({ view -> Bool in view is UITextField }) as? UITextField
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/AutocompleteClient/Utils/UI/UIView+FadeInOut.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+FadeInOut.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIView {
12 | func fadeIn(duration: TimeInterval, completion: ((Bool) -> Void)? = nil) {
13 | self.alpha = 0.0
14 | UIView.animate(withDuration: duration, animations: { [weak self] in
15 | self?.alpha = 1.0
16 | }, completion: completion)
17 | }
18 |
19 | func fadeOutAndRemove(duration: TimeInterval, completion: ((Bool) -> Void)? = nil) {
20 | UIView.animate(withDuration: duration, animations: { [weak self] in
21 | self?.alpha = 0.0
22 | }, completion: { [weak self] completed in
23 | self?.removeFromSuperview()
24 | completion?(completed)
25 | })
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/AutocompleteClient/Utils/UI/UIView+FindSubview.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+FindSubview.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | extension UIView {
13 | func findSubview(_ filter: (UIView) -> Bool) -> UIView? {
14 | for view in self.subviews {
15 | if filter(view) {
16 | return view
17 | } else if let subview = view.findSubview(filter) {
18 | return subview
19 | }
20 | }
21 | return nil
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/API/Error/ErrorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ErrorTests.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import XCTest
11 |
12 | class ErrorTests: XCTestCase {
13 |
14 | func testUnknownErrorHasCorrectCode() {
15 | XCTAssertEqual(NSError.unknownError().code, kConstructorUnknownErrorCode)
16 | }
17 |
18 | func testParseErrorHasCorrectCode() {
19 | XCTAssertEqual(NSError.jsonParseError().code, kConstructorJSONErrorCode)
20 | }
21 |
22 | func testCIOErrorReturnsNonNilErrorDescription() {
23 | XCTAssertNotNil(CIOError(errorType: .invalidResponse).errorDescription)
24 | }
25 |
26 | func testCIOErrorWithReturnsNonNilErrorMessage() {
27 | XCTAssertNotNil(CIOError(errorType: .badRequest, errorMessage: "Invalid parameter supplied with the request.").errorMessage)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/API/Parser/MockResponseParserDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MockResponseParserDelegate.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import Foundation
11 |
12 | class MockResponseParserDelegate: NSObject, ResponseParserDelegate {
13 |
14 | var shouldParseResultInGroup: ((_ result: CIOResult, _ group: CIOGroup?) -> Bool)? = { _, _ in return true }
15 |
16 | func shouldParseResult(result: CIOResult, inGroup group: CIOGroup?) -> Bool? {
17 | return self.shouldParseResultInGroup?(result, group)
18 | }
19 |
20 | func maximumGroupsShownPerResult(result: CIOResult, at index: Int) -> Int {
21 | return 1
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/Logic/Request/Matchers/CIOBuilder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOBuilder.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import XCTest
10 |
11 | class CIOBuilder {
12 |
13 | let expectation: XCTestExpectation
14 | let builder: Builder
15 |
16 | init(expectation: String, builder: @escaping Builder) {
17 | self.expectation = XCTestExpectation(description: expectation)
18 | self.builder = builder
19 | }
20 |
21 | func create() -> Builder {
22 | return { request in
23 | // at this point we know that request has been made and we can fullfil the expectation and delegate the request object
24 | // to the builder provided
25 | self.expectation.fulfill()
26 | return self.builder(request)
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/Logic/Request/Matchers/Matcher+Regex.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Matcher+Regex.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import XCTest
10 |
11 | // Returns a MockingJay Matcher if the URL string matches a regex
12 | public func regex(_ pattern: String, prepare: Bool = true) -> Matcher {
13 | return { request in
14 | let absoluteURLString = request.url!.absoluteString
15 |
16 | let preparedPattern = prepare ? prepareRegexPattern(pattern) : pattern
17 | do {
18 | let matchRange = try NSRegularExpression(pattern: preparedPattern, options: []).rangeOfFirstMatch(in: absoluteURLString, options: [], range: NSRange(location: 0, length: absoluteURLString.count))
19 | return matchRange.location == 0 && matchRange.length == absoluteURLString.count
20 | } catch {
21 | return false
22 | }
23 | }
24 | }
25 |
26 | // escape occurences of '?' and '/'
27 | private func prepareRegexPattern(_ pattern: String) -> String {
28 | return pattern.replacingOccurrences(of: "/", with: "\\/")
29 | .replacingOccurrences(of: "?", with: "\\?")
30 | }
31 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/Logic/Request/Mock/CIOGroup+Mock.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOGroup+Mock.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import ConstructorAutocomplete
10 | import XCTest
11 |
12 | public extension CIOGroup {
13 | class func mock(withName name: String? = nil) -> CIOGroup {
14 | let naem = name ?? "group"
15 | return CIOGroup(displayName: naem, groupID: naem, path: "path/to/group")
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/Logic/Request/Mock/CIOResult+Mock.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOAutocompleteResult+Mock.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import ConstructorAutocomplete
10 | import XCTest
11 |
12 | public extension CIOAutocompleteResult {
13 |
14 | class func mock(withValue value: String, group: CIOGroup? = nil) -> CIOAutocompleteResult {
15 | let json: [String: Any] = TestResource.load(name: TestResource.Response.singleResultJSONFilename).toJSONDictionary()!
16 | return CIOAutocompleteResult(result: CIOResult(json: json)!, group: group)
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/Logic/Request/Mock/MockCommons.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MockCommons.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import OHHTTPStubs
10 | import XCTest
11 |
12 | public typealias Matcher = OHHTTPStubsTestBlock
13 | public typealias Builder = OHHTTPStubsResponseBlock
14 |
15 | public func http(_ statusCode: Int32, data: Data = "".data(using: String.Encoding.utf8)!) -> OHHTTPStubsResponseBlock {
16 | return { _ in
17 | return OHHTTPStubsResponse(data: data, statusCode: statusCode, headers: nil)
18 | }
19 | }
20 |
21 | public func noConnectivity() -> OHHTTPStubsResponseBlock {
22 | return { _ in
23 | let error = NSError(domain: NSURLErrorDomain, code: URLError.notConnectedToInternet.rawValue, userInfo: nil)
24 | return OHHTTPStubsResponse(error: error)
25 | }
26 | }
27 |
28 | @discardableResult
29 | public func stub(_ matcher: @escaping Matcher, _ builder: @escaping Builder) -> OHHTTPStubsDescriptor {
30 | return stub(condition: matcher, response: builder)
31 | }
32 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/Logic/Request/QueryItemCollection/QueryItemCollectionTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // QueryItemCollectionTests.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import XCTest
11 |
12 | class QueryItemCollectionTests: XCTestCase {
13 |
14 | func testQueryItemCollection_Remove() {
15 | var collection = QueryItemCollection()
16 | collection.remove(name: "key")
17 | }
18 |
19 | func testQueryItemCollection_SubscriptGetter() {
20 | let collection = QueryItemCollection()
21 | _ = collection["key"]
22 | }
23 |
24 | func testQueryItemCollection_SubscriptSetter() {
25 | var collection = QueryItemCollection()
26 | collection["key"] = [URLQueryItem(name: "name", value: "value")]
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/Logic/Session/ClosureDateProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ClosureDateProvider.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import UIKit
11 |
12 | class ClosureDateProvider: DateProvider {
13 |
14 | var provideDateClosure: () -> Date
15 |
16 | init(provideDateClosure: @escaping () -> Date) {
17 | self.provideDateClosure = provideDateClosure
18 | }
19 |
20 | func provideDate() -> Date {
21 | return self.provideDateClosure()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/Logic/Session/ClosureSessionManagerDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ClosureSessionManagerDelegate.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import ConstructorAutocomplete
10 |
11 | class ClosureSessionManagerDelegate: CIOSessionManagerDelegate {
12 |
13 | let sessionChangeHandler: (_ from: Int, _ to: Int) -> Void
14 |
15 | init(sessionChangeHandler: @escaping (_ from: Int, _ to: Int) -> Void) {
16 | self.sessionChangeHandler = sessionChangeHandler
17 | }
18 |
19 | func sessionDidChange(from: Int, to: Int) {
20 | self.sessionChangeHandler(from, to)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/Logic/Session/NoSessionLoader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NoSessionLoader.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 |
11 | class NoSessionLoader: SessionLoader {
12 | func loadSession() -> Session? {
13 | return nil
14 | }
15 | func saveSession(_ session: Session) {}
16 |
17 | func clearSession() {}
18 | }
19 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/UI/SearchBar/SearchBarTextFieldTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchBarTextFieldTests.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import XCTest
11 |
12 | class SearchBarTextFieldTests: XCTestCase {
13 |
14 | func testTextFieldExtractFromSearchBar() {
15 | let searchBar = UISearchBar(frame: CGRect.zero)
16 | searchBar.layoutIfNeeded()
17 | XCTAssertNotNil(searchBar.searchTextField())
18 | }
19 |
20 | func testCustomSearchBar_WithDefaultInitializer() {
21 | let searchBar = CustomSearchBar()
22 | searchBar.setShowsCancelButton(true, animated: true)
23 | }
24 |
25 | func testCustomSearchBar_WithFrameInitializer() {
26 | let searchBar = CustomSearchBar(frame: .zero)
27 | searchBar.setShowsCancelButton(true, animated: true)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/UI/ViewModel/AutocompleteResultCountTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteResultCountTests.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import ConstructorAutocomplete
10 | import XCTest
11 |
12 | class AutocompleteResultCountTests: XCTestCase {
13 |
14 | func testAutocompleteResultCount_NumResultsInitializer() {
15 | let resultCount = AutocompleteResultCount(numResults: 1)
16 | XCTAssertNotNil(resultCount.numResults)
17 | XCTAssertNil(resultCount.numResultsForSection)
18 | }
19 |
20 | func testAutocompleteResultCount_NumResultsForSectionInitializer() {
21 | let resultCount = AutocompleteResultCount(numResultsForSection: [:])
22 | XCTAssertNil(resultCount.numResults)
23 | XCTAssertNotNil(resultCount.numResultsForSection)
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/UI/ViewModel/AutocompleteResultTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteResultTests.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import ConstructorAutocomplete
10 | import XCTest
11 |
12 | class AutocompleteResultTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testIsAfter_ifCorrectTimestampsArePassed() {
25 | let query = CIOAutocompleteQuery(query: "")
26 | let earlyResult = AutocompleteResult(query: query, timestamp: 10)
27 | let lateResult = AutocompleteResult(query: query, timestamp: 20)
28 | XCTAssertTrue(lateResult.isInitiatedAfter(result: earlyResult), "isAfter should return true if earlier initiated result is passed as a parameter")
29 | }
30 |
31 | func testIsAfter_ifIncorrectTimestampsArePassed() {
32 | let query = CIOAutocompleteQuery(query: "")
33 | let earlyResult = AutocompleteResult(query: query, timestamp: 20)
34 | let lateResult = AutocompleteResult(query: query, timestamp: 10)
35 | XCTAssertFalse(lateResult.isInitiatedAfter(result: earlyResult), "isAfter should return false if later initiated result is passed as a parameter")
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/FW/UI/ViewModel/ClosureAutocompleteViewModelDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ClosureAutocompleteViewModelDelegate.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import ConstructorAutocomplete
10 | import UIKit
11 |
12 | public class ClosureAutocompleteViewModelDelegate: AutocompleteViewModelDelegate {
13 |
14 | public var onIgnoreResult: ((AutocompleteResult) -> Void)?
15 | public var onSetResult: ((AutocompleteResult) -> Void)?
16 |
17 | public init(viewModel: AutocompleteViewModel) {
18 | viewModel.delegate = self
19 | }
20 |
21 | public func viewModel(_ viewModel: AbstractAutocompleteViewModel, didSetResult result: AutocompleteResult) {
22 | self.onSetResult?(result)
23 | }
24 |
25 | public func viewModel(_ viewModel: AbstractAutocompleteViewModel, didIgnoreResult result: AutocompleteResult) {
26 | self.onIgnoreResult?(result)
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Resources/response_browse_facet_options_json.json:
--------------------------------------------------------------------------------
1 | {
2 | "response": {
3 | "facets": [
4 | {
5 | "display_name": "Brand",
6 | "name": "brand",
7 | "type": "multiple",
8 | "options": [
9 | {
10 | "status": "",
11 | "count": 2460,
12 | "display_name": "Brand1",
13 | "value": "brand1",
14 | "data": null
15 | },
16 | {
17 | "status": "",
18 | "count": 662,
19 | "display_name": "Brand2",
20 | "value": "brand2",
21 | "data": null
22 | },
23 | {
24 | "status": "",
25 | "count": 409,
26 | "display_name": "Brand3",
27 | "value": "brand3",
28 | "data": null
29 | }
30 | ],
31 | "hidden": false,
32 | "data": {}
33 | }
34 | ]
35 | },
36 | "result_id": "8943b599-4d16-432a-ba28-cb9eb95e4625",
37 | "request": {
38 | "facet_name": "brand",
39 | "fmt_options": {
40 | "show_hidden_facets": true,
41 | "groups_start": "current",
42 | "groups_max_depth": 1,
43 | "show_hidden_fields": false,
44 | "show_protected_facets": false
45 | },
46 | "term": "",
47 | "page": 1,
48 | "num_results_per_page": 20,
49 | "sort_by": "relevance",
50 | "sort_order": "descending",
51 | "section": "Products"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Resources/response_browse_facets_json.json:
--------------------------------------------------------------------------------
1 | {
2 | "response": {
3 | "facets": [
4 | {
5 | "display_name": "Brand",
6 | "name": "brand",
7 | "type": "multiple",
8 | "hidden": false,
9 | "data": {}
10 | },
11 | {
12 | "display_name": "Category",
13 | "name": "category",
14 | "type": "multiple",
15 | "hidden": false,
16 | "data": {}
17 | },
18 | {
19 | "display_name": "Collection",
20 | "name": "collection",
21 | "type": "multiple",
22 | "hidden": false,
23 | "data": {}
24 | },
25 | {
26 | "display_name": "Lining Level",
27 | "name": "lining",
28 | "type": "multiple",
29 | "hidden": false,
30 | "data": {}
31 | },
32 | {
33 | "display_name": "Color",
34 | "name": "color",
35 | "type": "multiple",
36 | "hidden": false,
37 | "data": {}
38 | }
39 | ],
40 | "total_num_results": 9
41 | },
42 | "result_id": "aa13f189-7820-49c0-bc4f-735f75c2dcdc",
43 | "request": {
44 | "page": 1,
45 | "num_results_per_page": 5,
46 | "term": "",
47 | "fmt_options": {
48 | "groups_start": "current",
49 | "groups_max_depth": 1,
50 | "show_hidden_facets": false,
51 | "show_hidden_fields": false,
52 | "show_protected_facets": false
53 | },
54 | "sort_by": "relevance",
55 | "sort_order": "descending",
56 | "section": "Products"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Resources/response_json_single_result.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "groups": [{
4 | "display_name": "Drama",
5 | "group_id": "18",
6 | "path": null
7 | },
8 | {
9 | "display_name": "Adventure",
10 | "group_id": "12",
11 | "path": null
12 | },
13 | {
14 | "display_name": "Fantasy",
15 | "group_id": "14",
16 | "path": null
17 | },
18 | {
19 | "display_name": "Family",
20 | "group_id": "10751",
21 | "path": null
22 | },
23 | {
24 | "display_name": "Action",
25 | "group_id": "28",
26 | "path": null
27 | },
28 | {
29 | "display_name": "Animation",
30 | "group_id": "16",
31 | "path": null
32 | },
33 | {
34 | "display_name": "Science Fiction",
35 | "group_id": "878",
36 | "path": null
37 | }
38 | ],
39 | "id": "titans"
40 | },
41 | "matched_terms": [
42 | "titans"
43 | ],
44 | "value": "titans"
45 | }
46 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Resources/response_quiz_next_question.json:
--------------------------------------------------------------------------------
1 | {
2 | "next_question": {
3 | "id": 1,
4 | "title": "Sample single select question",
5 | "description": "Sample description",
6 | "type": "single",
7 | "cta_text": "Next",
8 | "images": {
9 | "primary_url": "https://example.com/image",
10 | "primary_alt": "Example image",
11 | "secondary_url": null,
12 | "secondary_alt": null
13 | },
14 | "options": [
15 | {
16 | "id": 1,
17 | "value": "Who",
18 | "attribute": {
19 | "name": "group_id",
20 | "value": "test-value"
21 | },
22 | "images": {
23 | "primary_url": "https://example.com/image",
24 | "primary_alt": "Example image",
25 | "secondary_url": null,
26 | "secondary_alt": null
27 | }
28 | },
29 | {
30 | "id": 2,
31 | "value": "What",
32 | "attribute": {
33 | "name": "group_id",
34 | "value": "test-value"
35 | },
36 | "images": null
37 | }
38 | ]
39 | },
40 | "quiz_version_id": "11db5ac7-67e1-4000-9000-414d8425cab3",
41 | "quiz_session_id": "session-67e1-4000-9000-414d8425cab3",
42 | "quiz_id": "123"
43 | }
44 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Resources/response_search_redirect.json:
--------------------------------------------------------------------------------
1 | {
2 | "request": {
3 | "fmt_options": {
4 | "groups_max_depth": 1,
5 | "groups_start": "current"
6 | },
7 | "num_results_per_page": 24,
8 | "page": 1,
9 | "section": "Products",
10 | "sort_by": "relevance",
11 | "sort_order": "descending",
12 | "term": "dior",
13 | "us": ["COUNTRY_US"]
14 | },
15 | "response": {
16 | "redirect": {
17 | "data": {
18 | "match_id": 16257,
19 | "rule_id": 8860,
20 | "url": "/brand/dior"
21 | },
22 | "matched_terms": ["dior"],
23 | "matched_user_segments": null
24 | }
25 | },
26 | "result_id": "cc5752d6-41a5-4fdf-a461-622d91306ee2"
27 | }
28 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Test Utils/Bundle/Bundle+Test.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Bundle+Test.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import XCTest
10 |
11 | extension Bundle {
12 | class func testBundle() -> Bundle {
13 | // pass any class from our test target
14 | return Bundle(for: CIOAutocompleteResponseParserTests.self)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Test Utils/CIOResponse+SearchSuggestions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CIOAutocompleteResponse+SearchSuggestions.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import ConstructorAutocomplete
10 | import XCTest
11 |
12 | extension CIOAutocompleteResponse {
13 | func getSearchSuggestions() -> [CIOAutocompleteResult]? {
14 | return self.sections["Search Suggestions"]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Test Utils/Constants/TestConstants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestConstants.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import XCTest
11 |
12 | let kRegexTimestamp = "[1-9][0-9]*"
13 | let kRegexClientID = "([A-Z0-9-])*"
14 | let kRegexSession = "[0-9]*"
15 | let kRegexAutocompleteKey = "[a-zA-Z-_0-9]*"
16 | let kRegexVersion = "cioios-[\\d\\.]*::[\\d\\.]*"
17 |
18 | struct TestConstants {
19 | static let defaultUserInterfaceExpectationTimeout: TimeInterval = 50.0
20 | static let defaultExpectationTimeout: TimeInterval = 1.5
21 | static let testApiKey = "key_OucJxxrfiTVUQx0C"
22 | static let testConfig = ConstructorIOConfig(apiKey: testApiKey)
23 | static let defaultSegments = "us=cio-app&us=cio-ios"
24 |
25 | static func testConstructor(_ config: ConstructorIOConfig = TestConstants.testConfig) -> ConstructorIO {
26 | let constructor = ConstructorIO(config: config)
27 | constructor.sessionManager = CIOSessionManager(dateProvider: CurrentTimeDateProvider(), timeout: Constants.Query.sessionIncrementTimeoutInSeconds, sessionLoader: NoSessionLoader())
28 | return constructor
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Test Utils/JSON/Data+ToJSON.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String+ToJSON.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import XCTest
10 |
11 | public extension Data {
12 | func toJSONDictionary() -> [String: Any]? {
13 | do {
14 | return try JSONSerialization.jsonObject(with: self, options: []) as? [String: Any]
15 | } catch {
16 | return nil
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Test Utils/XCTest/ExpectationHandler.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExpectationHandler.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import XCTest
10 |
11 | class ExpectationHandler {
12 | let expectation: XCTestExpectation
13 |
14 | init(expectation: XCTestExpectation) {
15 | self.expectation = expectation
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Test Utils/XCTest/XCTest+TimeoutFail.swift:
--------------------------------------------------------------------------------
1 | //
2 | // XCTest+TimeoutFail.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import XCTest
10 |
11 | extension XCTestCase {
12 |
13 | func defaultTimeoutFailureHandler() -> ((_ error: Error?) -> Void) {
14 | return { error in
15 | if error != nil {
16 | XCTFail("Test timed out.")
17 | }
18 | }
19 | }
20 |
21 | func waitForExpectationWithDefaultHandler(_ timeout: TimeInterval = TestConstants.defaultExpectationTimeout) {
22 | self.waitForExpectations(timeout: timeout, handler: self.defaultTimeoutFailureHandler())
23 | }
24 |
25 | func wait(for expectation: XCTestExpectation) {
26 | self.wait(for: [expectation], timeout: 1.0)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Utils/Color/UIColorRGBConversionTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColorRGBConversionTests.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import XCTest
11 |
12 | class UIColorRGBConversionTests: XCTestCase {
13 |
14 | func testColor_RGBInitializer() {
15 | let color = UIColor.RGB(250, green: 200, blue: 33)
16 | XCTAssertNotNil(color)
17 | }
18 |
19 | func testColor_RGBAInitializer() {
20 | let color = UIColor.RGBA(250, green: 200, blue: 33, alpha: 0.5)
21 | XCTAssertNotNil(color)
22 | }
23 |
24 | func testColor_HexInitializer() {
25 | let color = UIColor.hex(rgb: 123456)
26 | XCTAssertNotNil(color)
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Utils/String/SearchSuggestionStringConversionTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchSuggestionStringConversionTests.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import XCTest
11 |
12 | class SearchSuggestionStringConversionTests: XCTestCase {
13 |
14 | func testValidSearchSuggestionString() {
15 | XCTAssertTrue("SEARCH SuggestionS ".isSearchSuggestionString())
16 | }
17 |
18 | func testInvalidSearchSuggestionString() {
19 | XCTAssertFalse("SEARCH Suggestionz".isSearchSuggestionString())
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Utils/String/StringTrimTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StringTrimTests.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import XCTest
11 |
12 | class StringTrimTests: XCTestCase {
13 |
14 | func testStrinTrimRemovedTrailingSpaces() {
15 | let original = "abc "
16 | XCTAssertEqual(original.trim(), "abc")
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/AutocompleteClientTests/Utils/UI/UIViewAnimationTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewAnimationTests.swift
3 | // AutocompleteClientTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | @testable import ConstructorAutocomplete
10 | import XCTest
11 |
12 | class UIViewAnimationTests: XCTestCase {
13 |
14 | func testViewFadeIn() {
15 | let expectation = XCTestExpectation(description: "View alpha should be 1 after completion handler is called.")
16 |
17 | let view = UIView(frame: .zero)
18 | view.alpha = 0
19 |
20 | view.fadeIn(duration: 0.5, completion: { _ in
21 | XCTAssertEqual(view.alpha, 1.0)
22 | expectation.fulfill()
23 | })
24 |
25 | self.wait(for: [expectation], timeout: 1.0)
26 | }
27 |
28 | func testViewFadeOut() {
29 | let expectation = XCTestExpectation(description: "View alpha should be 0 after completion handler is called.")
30 |
31 | let view = UIView(frame: .zero)
32 | view.alpha = 1
33 |
34 | view.fadeOutAndRemove(duration: 0.5, completion: { _ in
35 | XCTAssertEqual(view.alpha, 0.0)
36 | expectation.fulfill()
37 | })
38 |
39 | self.wait(for: [expectation], timeout: 1.0)
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/ConstructorAutocomplete.dia:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/ConstructorAutocomplete.dia
--------------------------------------------------------------------------------
/ConstructorAutocomplete.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = 'ConstructorAutocomplete'
3 | spec.version = '4.1.0'
4 | spec.license = { :type => 'MIT', :file => 'LICENSE' }
5 | spec.homepage = 'https://www.constructor.io'
6 | spec.authors = { 'Zubin Tiku' => 'zubin@constructor.io', 'Christopher Gee' => 'christopher@constructor.io', 'Jimmy Li' => 'jimmy@constructor.io' }
7 | spec.summary = 'Constructor.io iOS Client'
8 | spec.source = { :git => 'https://github.com/Constructor-io/constructorio-client-swift.git', :tag => 'v4.1.0' }
9 | spec.platform = :ios, '11.0'
10 | spec.source_files = 'AutocompleteClient/**/*.swift'
11 | spec.framework = 'UIKit'
12 | spec.swift_versions = ['4.0', '4.1', '4.2', '5']
13 | spec.ios.resource_bundle = { 'ConstructorAutocomplete' => ['AutocompleteClient/Resources/*.png', 'AutocompleteClient/**/*.xib'] }
14 | end
15 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source "https://rubygems.org"
4 |
5 | gem 'slather'
6 | gem 'jazzy'
7 | gem 'xcodeproj'
8 | gem "rexml", ">= 3.3.6"
9 |
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Constructor.io Corporation
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
13 | all 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
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.1
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "ConstructorIO",
6 |
7 | platforms: [
8 | .iOS(.v11)
9 | ],
10 | products: [
11 | .library(name: "ConstructorAutocomplete", targets: ["ConstructorAutocomplete"])
12 | ],
13 | targets: [
14 | .target(name: "ConstructorAutocomplete",
15 | path: "AutocompleteClient/")
16 | ]
17 | )
18 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | xcodeproj "AutocompleteClient.xcodeproj"
2 |
3 | source 'https://github.com/CocoaPods/Specs.git'
4 |
5 | use_frameworks!
6 |
7 | platform :ios, '11.0'
8 |
9 | inhibit_all_warnings!
10 |
11 | target 'UserApplication' do
12 | pod 'Kingfisher'
13 | end
14 |
15 | target 'AutocompleteClientTests' do
16 | pod 'OHHTTPStubs/Swift'
17 | end
18 |
19 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Kingfisher (4.10.1)
3 | - OHHTTPStubs/Core (6.1.0)
4 | - OHHTTPStubs/Default (6.1.0):
5 | - OHHTTPStubs/Core
6 | - OHHTTPStubs/JSON
7 | - OHHTTPStubs/NSURLSession
8 | - OHHTTPStubs/OHPathHelpers
9 | - OHHTTPStubs/JSON (6.1.0):
10 | - OHHTTPStubs/Core
11 | - OHHTTPStubs/NSURLSession (6.1.0):
12 | - OHHTTPStubs/Core
13 | - OHHTTPStubs/OHPathHelpers (6.1.0)
14 | - OHHTTPStubs/Swift (6.1.0):
15 | - OHHTTPStubs/Default
16 |
17 | DEPENDENCIES:
18 | - Kingfisher
19 | - OHHTTPStubs/Swift
20 |
21 | SPEC REPOS:
22 | https://github.com/cocoapods/specs.git:
23 | - Kingfisher
24 | - OHHTTPStubs
25 |
26 | SPEC CHECKSUMS:
27 | Kingfisher: c148cd7b47ebde9989f6bc7c27dcaa79d81279a0
28 | OHHTTPStubs: 1e21c7d2c084b8153fc53d48400d8919d2d432d0
29 |
30 | PODFILE CHECKSUM: 8e6d7727bc494546363e0c7b4bb5c24a0e69cf70
31 |
32 | COCOAPODS: 1.7.3
33 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Wei Wang
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 |
23 |
--------------------------------------------------------------------------------
/Pods/Kingfisher/Sources/Box.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Box.swift
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 2018/3/17.
6 | // Copyright (c) 2018 Wei Wang
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import Foundation
27 |
28 | class Box {
29 | let value: T
30 |
31 | init(_ value: T) {
32 | self.value = value
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Kingfisher (4.10.1)
3 | - OHHTTPStubs/Core (6.1.0)
4 | - OHHTTPStubs/Default (6.1.0):
5 | - OHHTTPStubs/Core
6 | - OHHTTPStubs/JSON
7 | - OHHTTPStubs/NSURLSession
8 | - OHHTTPStubs/OHPathHelpers
9 | - OHHTTPStubs/JSON (6.1.0):
10 | - OHHTTPStubs/Core
11 | - OHHTTPStubs/NSURLSession (6.1.0):
12 | - OHHTTPStubs/Core
13 | - OHHTTPStubs/OHPathHelpers (6.1.0)
14 | - OHHTTPStubs/Swift (6.1.0):
15 | - OHHTTPStubs/Default
16 |
17 | DEPENDENCIES:
18 | - Kingfisher
19 | - OHHTTPStubs/Swift
20 |
21 | SPEC REPOS:
22 | https://github.com/cocoapods/specs.git:
23 | - Kingfisher
24 | - OHHTTPStubs
25 |
26 | SPEC CHECKSUMS:
27 | Kingfisher: c148cd7b47ebde9989f6bc7c27dcaa79d81279a0
28 | OHHTTPStubs: 1e21c7d2c084b8153fc53d48400d8919d2d432d0
29 |
30 | PODFILE CHECKSUM: 8e6d7727bc494546363e0c7b4bb5c24a0e69cf70
31 |
32 | COCOAPODS: 1.7.3
33 |
--------------------------------------------------------------------------------
/Pods/OHHTTPStubs/LICENSE:
--------------------------------------------------------------------------------
1 | - MIT LICENSE -
2 |
3 | Copyright (c) 2012 Olivier Halligon
4 |
5 | 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:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | 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.
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 4.10.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Kingfisher : NSObject
3 | @end
4 | @implementation PodsDummy_Kingfisher
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "Kingfisher.h"
14 |
15 | FOUNDATION_EXPORT double KingfisherVersionNumber;
16 | FOUNDATION_EXPORT const unsigned char KingfisherVersionString[];
17 |
18 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher.modulemap:
--------------------------------------------------------------------------------
1 | framework module Kingfisher {
2 | umbrella header "Kingfisher-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Kingfisher/Kingfisher.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | OTHER_LDFLAGS = $(inherited) -framework "CFNetwork"
4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -suppress-warnings
5 | PODS_BUILD_DIR = ${BUILD_DIR}
6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Kingfisher
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/OHHTTPStubs/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 6.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 6.1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_OHHTTPStubs : NSObject
3 | @end
4 | @implementation PodsDummy_OHHTTPStubs
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "Compatibility.h"
14 | #import "OHHTTPStubs.h"
15 | #import "OHHTTPStubsResponse.h"
16 | #import "OHHTTPStubsResponse+JSON.h"
17 | #import "NSURLRequest+HTTPBodyTesting.h"
18 | #import "OHPathHelpers.h"
19 | #import "Compatibility.h"
20 |
21 | FOUNDATION_EXPORT double OHHTTPStubsVersionNumber;
22 | FOUNDATION_EXPORT const unsigned char OHHTTPStubsVersionString[];
23 |
24 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs.modulemap:
--------------------------------------------------------------------------------
1 | framework module OHHTTPStubs {
2 | umbrella header "OHHTTPStubs-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/OHHTTPStubs/OHHTTPStubs.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "Foundation"
4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -suppress-warnings
5 | PODS_BUILD_DIR = ${BUILD_DIR}
6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_ROOT = ${SRCROOT}
8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/OHHTTPStubs
9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
10 | SKIP_INSTALL = YES
11 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-AutocompleteClientTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-AutocompleteClientTests/Pods-AutocompleteClientTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-AutocompleteClientTests/Pods-AutocompleteClientTests-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## OHHTTPStubs
5 |
6 | - MIT LICENSE -
7 |
8 | Copyright (c) 2012 Olivier Halligon
9 |
10 | 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:
11 |
12 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
13 |
14 | 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.
15 | Generated by CocoaPods - https://cocoapods.org
16 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-AutocompleteClientTests/Pods-AutocompleteClientTests-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_AutocompleteClientTests : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_AutocompleteClientTests
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-AutocompleteClientTests/Pods-AutocompleteClientTests-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_AutocompleteClientTestsVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_AutocompleteClientTestsVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-AutocompleteClientTests/Pods-AutocompleteClientTests.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs"
7 | OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "Foundation" -framework "OHHTTPStubs"
8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-AutocompleteClientTests/Pods-AutocompleteClientTests.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_AutocompleteClientTests {
2 | umbrella header "Pods-AutocompleteClientTests-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-AutocompleteClientTests/Pods-AutocompleteClientTests.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs/OHHTTPStubs.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/OHHTTPStubs"
7 | OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "Foundation" -framework "OHHTTPStubs"
8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserApplication/Pods-UserApplication-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserApplication/Pods-UserApplication-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## Kingfisher
5 |
6 | The MIT License (MIT)
7 |
8 | Copyright (c) 2018 Wei Wang
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 |
28 |
29 | Generated by CocoaPods - https://cocoapods.org
30 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserApplication/Pods-UserApplication-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_UserApplication : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_UserApplication
5 | @end
6 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserApplication/Pods-UserApplication-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_UserApplicationVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_UserApplicationVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserApplication/Pods-UserApplication.debug.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
7 | OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "Kingfisher"
8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserApplication/Pods-UserApplication.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_UserApplication {
2 | umbrella header "Pods-UserApplication-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-UserApplication/Pods-UserApplication.release.xcconfig:
--------------------------------------------------------------------------------
1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
4 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers"
5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
6 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" -iframework "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher"
7 | OTHER_LDFLAGS = $(inherited) -framework "CFNetwork" -framework "Kingfisher"
8 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
9 | PODS_BUILD_DIR = ${BUILD_DIR}
10 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
11 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
12 | PODS_ROOT = ${SRCROOT}/Pods
13 |
--------------------------------------------------------------------------------
/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Resources/Assets.xcassets/icon_empty.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_constructor.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "icon_constructor@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "icon_constructor@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Resources/Assets.xcassets/icon_empty.imageset/icon_constructor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/Resources/Assets.xcassets/icon_empty.imageset/icon_constructor.png
--------------------------------------------------------------------------------
/Resources/Assets.xcassets/icon_empty.imageset/icon_constructor@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/Resources/Assets.xcassets/icon_empty.imageset/icon_constructor@2x.png
--------------------------------------------------------------------------------
/Resources/Assets.xcassets/icon_empty.imageset/icon_constructor@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/Resources/Assets.xcassets/icon_empty.imageset/icon_constructor@3x.png
--------------------------------------------------------------------------------
/Resources/Assets.xcassets/icon_error.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_error.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "icon_error@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "icon_error@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Resources/Assets.xcassets/icon_error.imageset/icon_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/Resources/Assets.xcassets/icon_error.imageset/icon_error.png
--------------------------------------------------------------------------------
/Resources/Assets.xcassets/icon_error.imageset/icon_error@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/Resources/Assets.xcassets/icon_error.imageset/icon_error@2x.png
--------------------------------------------------------------------------------
/Resources/Assets.xcassets/icon_error.imageset/icon_error@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/Resources/Assets.xcassets/icon_error.imageset/icon_error@3x.png
--------------------------------------------------------------------------------
/Resources/constructor-io-error-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/Resources/constructor-io-error-icon.png
--------------------------------------------------------------------------------
/SearchFWTestApp/SearchFWTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SearchFWTestApp/SearchFWTestApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/SearchFWTestApp/SearchFWTestApp/Assets.xcassets/Logo/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/SearchFWTestApp/SearchFWTestApp/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UILaunchStoryboardName
24 | LaunchScreen
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/SearchFWTestApp/SearchFWTestAppTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SearchFWTestApp/SearchFWTestAppTests/SearchFWTestAppTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchFWTestAppTests.swift
3 | // Constructor.io
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import XCTest
10 | @testable import SearchFWTestApp
11 |
12 | class SearchFWTestAppTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_cart.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_cart.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "icon_cart@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "icon_cart@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_cart.imageset/icon_cart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_cart.imageset/icon_cart.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_cart.imageset/icon_cart@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_cart.imageset/icon_cart@2x.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_cart.imageset/icon_cart@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_cart.imageset/icon_cart@3x.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_clock.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_clock.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 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_clock.imageset/icon_clock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_clock.imageset/icon_clock.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_error_yellow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_error_yellow.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 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_error_yellow.imageset/icon_error_yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_error_yellow.imageset/icon_error_yellow.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_filter.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_filter.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 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_filter.imageset/icon_filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_filter.imageset/icon_filter.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_gear.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon-gear.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 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_gear.imageset/icon-gear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_gear.imageset/icon-gear.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_help.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_help.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 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_help.imageset/icon_help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_help.imageset/icon_help.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_logo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "constructor-io-logo.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 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_logo.imageset/constructor-io-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_logo.imageset/constructor-io-logo.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_sign_error.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_sign_error.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 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_sign_error.imageset/icon_sign_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_sign_error.imageset/icon_sign_error.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_sort.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_sort.jpg",
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 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_sort.imageset/icon_sort.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_sort.imageset/icon_sort.jpg
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_star.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icon_star.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 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/icon_star.imageset/icon_star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/icon_star.imageset/icon_star.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/img_logo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "img_logo.png",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/img_logo.imageset/img_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/img_logo.imageset/img_logo.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/sort_ascending.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "arrow_up.png",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/sort_ascending.imageset/arrow_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/sort_ascending.imageset/arrow_up.png
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/sort_descending.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "scale" : "2x"
10 | },
11 | {
12 | "idiom" : "universal",
13 | "filename" : "arrow_down.png",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/UserApplication/Assets.xcassets/sort_descending.imageset/arrow_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/UserApplication/Assets.xcassets/sort_descending.imageset/arrow_down.png
--------------------------------------------------------------------------------
/UserApplication/Common/BadgeView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BadgeView.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | class BadgeView: UIView {
12 |
13 | private var label: UILabel
14 |
15 | init(){
16 | self.label = UILabel(frame: .zero)
17 | super.init(frame: .zero)
18 | self.backgroundColor = UIColor.red
19 | self.clipsToBounds = true
20 |
21 | self.label.backgroundColor = .clear
22 | self.label.textAlignment = .center
23 | self.label.translatesAutoresizingMaskIntoConstraints = false
24 | self.label.textColor = UIColor.white
25 | self.label.adjustsFontSizeToFitWidth = true
26 | self.label.baselineAdjustment = .alignCenters
27 |
28 | self.label.font = UIFont.systemFont(ofSize: 10)
29 |
30 | self.addSubview(label)
31 | self.label.pinToSuperviewTop(2)
32 | self.label.pinToSuperviewBottom(2)
33 | self.label.pinToSuperviewLeft(2)
34 | self.label.pinToSuperviewRight(2)
35 | }
36 |
37 | func setValue(text: String){
38 | self.label.text = text
39 | self.label.layoutIfNeeded()
40 | self.label.setNeedsDisplay()
41 | }
42 |
43 | required init?(coder aDecoder: NSCoder) {
44 | fatalError("init(coder:) has not been implemented")
45 | }
46 |
47 | override func layoutSubviews() {
48 | super.layoutSubviews()
49 | self.layer.cornerRadius = self.frame.size.height/2
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/UserApplication/Common/Constructor/ConstructorIOProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ConstructorIOProvider.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import ConstructorAutocomplete
11 |
12 | protocol ConstructorIOProvider{
13 | func provideConstructorInstance() -> ConstructorIO
14 | }
15 |
--------------------------------------------------------------------------------
/UserApplication/CustomHighlighting/CustomAttributesProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomAttributesProvider.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 | import ConstructorAutocomplete
11 |
12 | class CustomAttributesProvider: CIOHighlightingAttributesProvider {
13 |
14 | func defaultSubstringAttributes() -> [NSAttributedString.Key: Any] {
15 | return [NSAttributedString.Key.foregroundColor: UIColor.darkGray, NSAttributedString.Key.font: UIFont(name: "Optima-Regular", size: 15)!]
16 | }
17 |
18 | func highlightedSubstringAttributes() -> [NSAttributedString.Key: Any] {
19 | return [NSAttributedString.Key.foregroundColor: UIColor.black, NSAttributedString.Key.font: UIFont(name: "Optima-Bold", size: 15)!]
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/UserApplication/CustomViews/Cell/Class/CustomTableViewCellTwo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomTableViewCellTwo.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 | import ConstructorAutocomplete
11 |
12 | class CustomTableViewCellTwo: UITableViewCell, CIOAutocompleteCell {
13 |
14 | func setup(result: CIOAutocompleteResult, searchTerm: String, highlighter: CIOHighlighter) {
15 | if let group = result.group{
16 | let groupString = NSMutableAttributedString()
17 | groupString.append(NSAttributedString(string: " in ", attributes: highlighter.attributesProvider.defaultSubstringAttributes()))
18 | groupString.append(NSAttributedString(string: group.displayName, attributes: highlighter.attributesProvider.highlightedSubstringAttributes()))
19 | self.textLabel?.attributedText = groupString
20 |
21 | self.imageView?.image = nil
22 | }else{
23 | self.textLabel?.attributedText = highlighter.highlight(searchTerm: searchTerm, itemTitle: result.result.value)
24 | self.imageView?.image = UIImage(named: "icon_clock")
25 | }
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/UserApplication/CustomViews/Error/CustomErrorView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomErrorView.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 | import ConstructorAutocomplete
11 |
12 | class CustomErrorView: UIView, CIOErrorView {
13 |
14 | @IBOutlet weak var labelError: UILabel!
15 |
16 | func asView() -> UIView {
17 | return self
18 | }
19 |
20 | func setErrorString(errorString: String) {
21 | self.labelError.text = errorString
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/UserApplication/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UIViewControllerBasedStatusBarAppearance
6 |
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Cart/Logic/CartItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CartItem.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | struct CartItem: Codable{
12 | let title: String
13 | let imageURL: String
14 | let price: Double
15 | var totalPrice: Double {
16 | return self.price * Double(self.quantity)
17 | }
18 | var quantity: Int
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Cart/UI/CartItemTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CartItemTableViewCell.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | class CartItemTableViewCell: UITableViewCell {
12 |
13 | @IBOutlet weak var labelTitle: UILabel!
14 | @IBOutlet weak var labelQuantity: UILabel!
15 | @IBOutlet weak var labelTotalPrice: UILabel!
16 | @IBOutlet weak var imageViewProduct: UIImageView!
17 |
18 | func setup(_ model: CartItemViewModel){
19 | self.labelTitle.text = model.title
20 | self.labelQuantity.text = model.quantity.string
21 | self.labelTotalPrice.text = model.singleItemPrice
22 | self.imageViewProduct.kf.setImage(with: URL(string: model.imageURL))
23 |
24 | self.labelTitle.font = UIFont.appFontSemiBold(18)
25 | self.labelTotalPrice.font = UIFont.appFont(17)
26 | self.labelTotalPrice.adjustsFontSizeToFitWidth = true
27 | self.labelQuantity.font = UIFont.appFont(11)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Cart/ViewModel/CartItemViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CartItemViewModel.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | struct CartItemViewModel {
12 | let title: String
13 | let imageURL: String
14 | let singleItemPrice: String
15 | let totalPrice: String
16 | var quantity: Quantity
17 |
18 | init(item: CartItem){
19 | self.title = item.title
20 | self.quantity = Quantity(value: item.quantity)
21 | self.imageURL = item.imageURL
22 | self.singleItemPrice = String(format: "$%.2f",item.price)
23 | self.totalPrice = String(format: "$%.2f",item.totalPrice)
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Cart/ViewModel/CartViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CartViewModel.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import ConstructorAutocomplete
11 |
12 | class CartViewModel {
13 |
14 | var items: [CartItemViewModel]
15 | let cart: Cart
16 | let constructor: ConstructorIO
17 |
18 | var totalPrice: String{
19 | return String(format: "$%.02f", cart.items.map({ $0.totalPrice }).reduce(0, +))
20 | }
21 |
22 | init(cart: Cart, constructor: ConstructorIO){
23 | self.cart = cart
24 | self.constructor = constructor
25 | self.items = []
26 | self.reloadItems()
27 | }
28 |
29 | func reloadItems(){
30 | self.items = cart.items.map{ CartItemViewModel(item: $0)}
31 | }
32 |
33 | func updateQuantity(newValue: Int, for index: Int) -> CartItemViewModel?{
34 | if let cartItem = self.cart.updateQuantity(newValue: newValue, for: index){
35 | let viewModel = CartItemViewModel(item: cartItem)
36 | items[index] = viewModel
37 | return viewModel
38 | }else{
39 | self.items.remove(at: index)
40 | return nil
41 | }
42 | }
43 |
44 | func removeItemAtIndex(_ index: Int){
45 | self.cart.items.remove(at: index)
46 | self.reloadItems()
47 | }
48 |
49 | func removeAllItems(){
50 | self.cart.items = []
51 | self.reloadItems()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Cart/ViewModel/Quantity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Quantity.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | struct Quantity{
12 | var value: Int
13 | var string: String{
14 | return "QTY. \(self.value)"
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Details/ViewModel/DetailsViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DetailsViewModel.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | struct DetailsViewModel{
13 | let title: String
14 | let price: Double
15 | var priceString: String{
16 | return "$\(self.price)"
17 | }
18 | let image: UIImage?
19 | let imageURL: String
20 | let description: String
21 |
22 | var titlePrice: String{
23 | return "\(self.title)\n\n\(self.priceString)"
24 | }
25 |
26 | let cart: Cart
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Filters/Delegate/FiltersSelectionDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FiltersDelegate.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import ConstructorAutocomplete
11 |
12 | protocol FiltersSelectionDelegate: AnyObject{
13 | func didSelect(filters: [Filter])
14 | }
15 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Filters/UI/Cells/FilterTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FilterTableViewCell.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | class FilterTableViewCell: UITableViewCell {
12 |
13 | @IBOutlet weak var labelTitle: UILabel!
14 |
15 | override func awakeFromNib() {
16 | super.awakeFromNib()
17 | // Initialization code
18 | }
19 |
20 | override func setSelected(_ selected: Bool, animated: Bool) {
21 | super.setSelected(selected, animated: animated)
22 |
23 | // Configure the view for the selected state
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Filters/UI/Header/Delegate/FilterHeaderDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FilterHeaderDelegate.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 |
11 | protocol FilterHeaderDelegate: class{
12 | func didTapOnSortView()
13 | func didTapOnFilterView()
14 | }
15 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Filters/UI/Header/FilterHeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FilterHeaderView.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | class FilterHeaderView: UIView {
12 |
13 | weak var tapDelegate: FilterHeaderDelegate?
14 | @IBOutlet weak var imageViewSort: UIImageView!
15 | @IBOutlet weak var labelSort: UILabel!
16 | @IBOutlet weak var labelFilter: UILabel!
17 | @IBOutlet weak var viewFilter: UIView!
18 | @IBOutlet weak var viewSort: UIView!
19 |
20 | class func instantiateFromNib() -> FilterHeaderView{
21 | let v = UINib(nibName: "FilterHeaderView", bundle: nil).instantiate(withOwner: nil, options: nil).first as! FilterHeaderView
22 | v.translatesAutoresizingMaskIntoConstraints = false
23 | return v
24 | }
25 |
26 | override func awakeFromNib() {
27 | super.awakeFromNib()
28 |
29 | self.viewFilter.isUserInteractionEnabled = true
30 | self.viewSort.isUserInteractionEnabled = true
31 |
32 | self.viewFilter.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTapOnViewFilter)))
33 | self.viewSort.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTapOnViewSort)))
34 |
35 | self.layer.borderWidth = 0.6
36 | self.layer.borderColor = UIColor.darkGray.withAlphaComponent(0.5).cgColor
37 | }
38 |
39 | @objc
40 | func didTapOnViewSort(){
41 | self.tapDelegate?.didTapOnSortView()
42 | }
43 |
44 | @objc
45 | func didTapOnViewFilter(){
46 | self.tapDelegate?.didTapOnFilterView()
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Filters/ViewModel/FacetOptionViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FacetOptonViewModel.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import ConstructorAutocomplete
11 |
12 | struct FacetOptionViewModel{
13 | let value: String
14 | let title: String
15 | var selected: Bool
16 | }
17 |
18 | extension FacetOptionViewModel{
19 | init(option: CIOFilterFacetOption){
20 | self.init(value: option.value, title: option.displayName, selected: false)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Filters/ViewModel/FacetViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Facet.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 | import ConstructorAutocomplete
11 |
12 | class FacetViewModel {
13 | let title: String
14 | var options: [FacetOptionViewModel]
15 |
16 | convenience init(facet: CIOFilterFacet){
17 | self.init(filterName: facet.displayName, options: facet.options.map(FacetOptionViewModel.init))
18 | }
19 |
20 | init(filterName: String, options: [FacetOptionViewModel]){
21 | self.title = filterName
22 | self.options = options
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Filters/ViewModel/FiltersViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FiltersViewModel.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 | import ConstructorAutocomplete
11 |
12 | class FiltersViewModel {
13 | let filters: [FacetViewModel]
14 | var changed: Bool = false
15 | weak var delegate: FiltersSelectionDelegate?
16 |
17 | var selectedFilters: [Filter]{
18 | return self.filters.reduce([Filter]()) { res, next in
19 | return res + next.options.filter{ $0.selected }
20 | .map({ return (key: next.title, value: $0.value) as Filter })
21 | }
22 | }
23 |
24 | init(filters: [FacetViewModel]){
25 | self.filters = filters
26 | }
27 |
28 | func toggle(indexPath: IndexPath){
29 | self.changed = true
30 | self.filters[indexPath.section].options[indexPath.row].selected.toggle()
31 | }
32 |
33 | func dismiss(){
34 | if self.changed{
35 | self.delegate?.didSelect(filters: self.selectedFilters)
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Search/UI/SearchCollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchCollectionViewCell.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 | import Kingfisher
11 |
12 | class SearchCollectionViewCell: UICollectionViewCell {
13 |
14 | @IBOutlet weak var imageView: UIImageView!
15 | @IBOutlet weak var labelProductName: UILabel!
16 | @IBOutlet weak var labelPrice: UILabel!
17 |
18 | override func awakeFromNib() {
19 | super.awakeFromNib()
20 |
21 | self.contentView.layer.borderColor = UIColor.black.withAlphaComponent(0.2).cgColor
22 | self.contentView.layer.borderWidth = 1
23 | self.contentView.layer.masksToBounds = true
24 | self.contentView.clipsToBounds = true
25 | }
26 |
27 | func setup(viewModel: SearchResultViewModel){
28 | self.labelProductName.text = viewModel.title
29 | self.labelPrice.text = viewModel.priceString
30 |
31 | self.imageView.kf.setImage(with: URL(string: viewModel.imageURL), placeholder: viewModel.fallbackImage())
32 | }
33 |
34 | override func prepareForReuse() {
35 | super.prepareForReuse()
36 | self.imageView.kf.cancelDownloadTask()
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Search/UI/SearchTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchTableViewCell.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | class SearchTableViewCell: UITableViewCell {
12 |
13 | override func awakeFromNib() {
14 | super.awakeFromNib()
15 | // Initialization code
16 | }
17 |
18 | override func setSelected(_ selected: Bool, animated: Bool) {
19 | super.setSelected(selected, animated: animated)
20 |
21 | // Configure the view for the selected state
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Search/UI/SearchTableViewCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Search/ViewModel/SearchResultViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SearchResultViewModel.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import ConstructorAutocomplete
11 | import UIKit
12 |
13 | public struct SearchResultViewModel{
14 |
15 | public let title: String
16 | public let price: Double
17 | public let priceString: String
18 | public let imageURL: String
19 | public let description: String
20 | public let fallbackImage: () -> UIImage
21 |
22 | public init(searchResult: CIOResult){
23 | self.title = searchResult.value
24 | self.price = searchResult.data.metadata["price"] as? Double ?? 0.00
25 | self.imageURL = searchResult.data.imageURL ?? ""
26 | self.fallbackImage = { return UIImage(named: "icon_logo")! }
27 |
28 | self.description = searchResult.data.metadata["description"] as? String ?? ""
29 | self.priceString = "$\(self.price)"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Sort/Delegate/SortSelectionDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SortSelectionDelegate.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import ConstructorAutocomplete
11 |
12 | protocol SortSelectionDelegate: AnyObject{
13 | func didSelect(sortOption: CIOSortOption?)
14 | }
15 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Sort/UI/SortOptionTableViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SortOptionTableViewCell.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 |
11 | class SortOptionTableViewCell: UITableViewCell {
12 |
13 | @IBOutlet weak var labelSort: UILabel!
14 | @IBOutlet weak var imageViewSort: UIImageView!
15 |
16 | override func awakeFromNib() {
17 | super.awakeFromNib()
18 | self.imageView?.contentMode = .scaleAspectFit
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Sort/UI/UIImage/UIImage+Sort.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Sort.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import ConstructorAutocomplete
11 | import UIKit
12 |
13 | extension UIImage{
14 | class func imageSortAscending() -> UIImage{
15 | return UIImage(named: "sort_ascending")!
16 | }
17 |
18 | class func imageSortDescending() -> UIImage{
19 | return UIImage(named: "sort_descending")!
20 | }
21 |
22 | class func imageForSortOrder(_ sortOrder: CIOSortOrder) -> UIImage{
23 | switch sortOrder {
24 | case .ascending:
25 | return self.imageSortAscending()
26 | case .descending:
27 | return self.imageSortDescending()
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Sort/ViewModel/SortOptionViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SortOptionViewModel.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import ConstructorAutocomplete
12 |
13 | struct SortOptionViewModel{
14 | var model: CIOSortOption
15 |
16 | let displayName: String
17 | let image: UIImage?
18 | var selected: Bool
19 |
20 | init(option: CIOSortOption){
21 | self.model = option
22 | self.displayName = option.displayName
23 | self.image = UIImage.imageForSortOrder(option.sortOrder)
24 | self.selected = false
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/UserApplication/Screens/Sort/ViewModel/SortViewModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SortViewModel.swift
3 | // UserApplication
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import ConstructorAutocomplete
11 |
12 | class SortViewModel{
13 | var items: [SortOptionViewModel]
14 | var selectedItem: SortOptionViewModel?{
15 | get{
16 | return self.items.first(where: { $0.selected })
17 | }
18 | }
19 | var changed: Bool
20 |
21 | weak var delegate: SortSelectionDelegate?
22 |
23 | init(items: [SortOptionViewModel]){
24 | self.items = items
25 | self.changed = false
26 | }
27 |
28 | func toggle(indexPath: IndexPath){
29 | self.changed = true
30 | for idx in 0.. UIColor {
13 | return self.RGBA(red, green: green, blue: blue, alpha: 255)
14 | }
15 |
16 | class func RGBA(_ red: Int, green: Int, blue: Int, alpha: CGFloat) -> UIColor {
17 | return UIColor(red: CGFloat(red) / 255.0, green: CGFloat(green)/255.0, blue: CGFloat(blue)/255.0, alpha: alpha)
18 | }
19 |
20 | class func hex(rgb: Int) -> UIColor {
21 | return self.RGB((rgb >> 16) & 0xFF, green: (rgb >> 8) & 0xFF, blue: rgb & 0xFF)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/UserApplication/Utils/UI/UIFont+AppFonts.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIFont+AppFonts.swift
3 | // UserApplication
4 | //
5 | // Created by Nikola Markovic on 10/25/19.
6 | // Copyright © 2019 xd. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIFont{
12 | static func appFontSemiBold(_ size: CGFloat) -> UIFont{
13 | return UIFont.systemFont(ofSize: size, weight: .semibold)
14 | }
15 |
16 | static func appFontBold(_ size: CGFloat) -> UIFont{
17 | return UIFont.systemFont(ofSize: size, weight: .bold)
18 | }
19 |
20 | static func appFont(_ size: CGFloat) -> UIFont{
21 | return UIFont.systemFont(ofSize: size)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/UserApplicationTests/DataSource/AutocompleteDataSourceWrapper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteDataSourceWrapper.swift
3 | // UserApplicationTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 | import ConstructorAutocomplete
11 |
12 | //class AutocompleteDataSourceWrapper: CIOAutocompleteDataSource {
13 | //
14 | // @objc
15 | // optional func customCellNib() -> UINib
16 | //
17 | // @objc
18 | // optional func customCellClass() -> AnyClass
19 | //
20 | // @objc
21 | // optional func styleSearchBar(searchBar: UISearchBar)
22 | //
23 | // @objc
24 | // optional func styleResultLabel(label: UILabel)
25 | //
26 | // @objc
27 | // optional func styleResultCell(cell: UITableViewCell)
28 | //
29 | // @objc
30 | // optional func fontNormal() -> UIFont
31 | //
32 | // @objc
33 | // optional func fontBold() -> UIFont
34 | //
35 | // @objc
36 | // optional func rowHeight() -> CGFloat
37 | //
38 | // @objc
39 | // optional func searchBarPlaceholder() -> String
40 | //
41 | // @objc
42 | // optional func backgroundView() -> UIView?
43 | //
44 | // @objc
45 | // optional func errorView() -> UIView?
46 | //}
47 |
--------------------------------------------------------------------------------
/UserApplicationTests/Delegate/AutocompleteDelegateWrapper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteDelegateWrapper.swift
3 | // UserApplicationTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import UIKit
10 | import ConstructorAutocomplete
11 |
12 | class AutocompleteDelegateWrapper: CIOAutocompleteDelegate {
13 |
14 | var onSelect: ((_ result: CIOAutocompleteResult) -> Void)?
15 | var onSearchPerformed: ((_ searchTerm: String) -> Void)?
16 | var onLoad: (() -> Void)?
17 | var onWillAppear: (() -> Void)?
18 |
19 | func autocompleteController(controller: CIOAutocompleteViewController, didSelectResult result: CIOAutocompleteResult) {
20 | self.onSelect?(result)
21 | }
22 |
23 | func autocompleteController(controller: CIOAutocompleteViewController, didPerformSearch searchTerm: String) {
24 | self.onSearchPerformed?(searchTerm)
25 | }
26 |
27 | func autocompleteControllerWillAppear(controller: CIOAutocompleteViewController) {
28 | self.onWillAppear?()
29 | }
30 |
31 | func autocompleteControllerDidLoad(controller: CIOAutocompleteViewController) {
32 | self.onLoad?()
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/UserApplicationTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/UserApplicationTests/Utils/CIOAutocompleteViewController+Show.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AutocompleteViewController+Show.swift
3 | // UserApplicationTests
4 | //
5 | // Copyright (c) Constructor.io Corporation. All rights reserved.
6 | // http://constructor.io/
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import ConstructorAutocomplete
12 |
13 | extension CIOAutocompleteViewController {
14 |
15 | class func instantiate() -> CIOAutocompleteViewController {
16 | let viewController = CIOAutocompleteViewController(config: TestConstants.testConfig)
17 | return viewController
18 | }
19 |
20 | func showInNewWindow() {
21 | let window = UIWindow(frame: UIScreen.main.bounds)
22 | window.rootViewController = self
23 |
24 | window.makeKeyAndVisible()
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/coverage.all.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Create coverage reports for all files
4 | rm -rf coverage-reports
5 | mkdir coverage-reports
6 | slather coverage --html --show --output-directory coverage-reports --ignore AutocompleteClientTests/\*
--------------------------------------------------------------------------------
/coverage.core.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Create coverage reports for core (non-UI) code
4 | rm -rf coverage-reports
5 | mkdir coverage-reports
6 | slather coverage --html --show --output-directory coverage-reports --ignore AutocompleteClientTests/\* --ignore AutocompleteClient/FW/UI/\* --ignore AutocompleteClient/Utils/\*\*/UI\*
--------------------------------------------------------------------------------
/docs/badge.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/docs/docsets/ConstructorAutocomplete.docset/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIdentifier
6 | com.jazzy.constructorautocomplete
7 | CFBundleName
8 | ConstructorAutocomplete
9 | DocSetPlatformFamily
10 | constructorautocomplete
11 | isDashDocset
12 |
13 | dashIndexFilePath
14 | index.html
15 | isJavaScriptEnabled
16 |
17 | DashDocSetFamily
18 | dashtoc
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/Documents/badge.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/Documents/img/carat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/Documents/img/carat.png
--------------------------------------------------------------------------------
/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/Documents/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/Documents/img/dash.png
--------------------------------------------------------------------------------
/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/Documents/img/gh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/Documents/img/gh.png
--------------------------------------------------------------------------------
/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/Documents/img/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/Documents/img/spinner.gif
--------------------------------------------------------------------------------
/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/docSet.dsidx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/docsets/ConstructorAutocomplete.docset/Contents/Resources/docSet.dsidx
--------------------------------------------------------------------------------
/docs/docsets/ConstructorAutocomplete.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/docsets/ConstructorAutocomplete.tgz
--------------------------------------------------------------------------------
/docs/img/carat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/img/carat.png
--------------------------------------------------------------------------------
/docs/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/img/dash.png
--------------------------------------------------------------------------------
/docs/img/gh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/img/gh.png
--------------------------------------------------------------------------------
/docs/img/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Constructor-io/constructorio-client-swift/43925c352742bb3bf3104c186a1e76935687aa00/docs/img/spinner.gif
--------------------------------------------------------------------------------