├── Images ├── logo.png ├── IMG_0690.PNG ├── IMG_0691.PNG ├── IMG_0692.PNG ├── IMG_0693.PNG ├── IMG_0694.PNG ├── IMG_0696.PNG ├── IMG_0697.PNG └── IMG_1234123.png ├── ICO-Visualizer ├── Assets.xcassets │ ├── Contents.json │ ├── AppIcon.appiconset │ │ ├── 20.png │ │ ├── 29.png │ │ ├── 40.png │ │ ├── 50.png │ │ ├── 57.png │ │ ├── 58.png │ │ ├── 60.png │ │ ├── 72.png │ │ ├── 76.png │ │ ├── 80.png │ │ ├── 87.png │ │ ├── 100.png │ │ ├── 1024.png │ │ ├── 114.png │ │ ├── 120.png │ │ ├── 144.png │ │ ├── 152.png │ │ ├── 167.png │ │ ├── 180.png │ │ └── Contents.json │ ├── header_logo.imageset │ │ ├── logo.png │ │ ├── logo-1.png │ │ ├── logo-2.png │ │ └── Contents.json │ ├── user_icon.imageset │ │ ├── icons8-user-64.png │ │ ├── icons8-user-65.png │ │ ├── icons8-user-66.png │ │ └── Contents.json │ ├── star_icon.imageset │ │ ├── icons8-stella-90.png │ │ ├── icons8-stella-90@2x.png │ │ ├── icons8-stella-90@3x.png │ │ └── Contents.json │ ├── back_icon.imageset │ │ ├── icons8-indietro-90.png │ │ ├── icons8-indietro-90@2x.png │ │ ├── icons8-indietro-90@3x.png │ │ └── Contents.json │ ├── like_icon.imageset │ │ ├── icons8-mi-piace-90.png │ │ ├── icons8-mi-piace-90@2x.png │ │ ├── icons8-mi-piace-90@3x.png │ │ └── Contents.json │ ├── search_icon.imageset │ │ ├── icons8-ricerca-50.png │ │ ├── icons8-ricerca-51.png │ │ ├── icons8-ricerca-52.png │ │ └── Contents.json │ ├── views_icon.imageset │ │ ├── icons8-visibile-90.png │ │ ├── icons8-visibile-90@2x.png │ │ ├── icons8-visibile-90@3x.png │ │ └── Contents.json │ ├── audio_on.imageset │ │ ├── icons8-volume-alto-100.png │ │ ├── icons8-volume-alto-100@2x.png │ │ ├── icons8-volume-alto-100@3x.png │ │ └── Contents.json │ ├── top_arrow.imageset │ │ ├── icons8-doppio-sù-100.png │ │ ├── icons8-doppio-sù-101.png │ │ ├── icons8-doppio-sù-102.png │ │ └── Contents.json │ ├── audio_off.imageset │ │ ├── icons8-nessun-audio-100.png │ │ ├── icons8-nessun-audio-100@2x.png │ │ ├── icons8-nessun-audio-100@3x.png │ │ └── Contents.json │ ├── home_icon.imageset │ │ ├── icons8-home-page-90 (1).png │ │ ├── icons8-home-page-90 (1)@2x.png │ │ ├── icons8-home-page-90 (1)@3x.png │ │ └── Contents.json │ ├── categories_icon.imageset │ │ ├── icons8-categoria-60.png │ │ ├── icons8-categoria-60@2x.png │ │ ├── icons8-categoria-60@3x.png │ │ └── Contents.json │ ├── external_icon.imageset │ │ ├── icons8-link-esterno-60.png │ │ ├── icons8-link-esterno-61.png │ │ ├── icons8-link-esterno-62.png │ │ └── Contents.json │ ├── reels_icon.imageset │ │ ├── icons8-instagram-reels-100.png │ │ ├── icons8-instagram-reels-100@2x.png │ │ ├── icons8-instagram-reels-100@3x.png │ │ └── Contents.json │ ├── settings_icon.imageset │ │ ├── icons8-impostazioni-120.png │ │ ├── icons8-impostazioni-120@2x.png │ │ ├── icons8-impostazioni-120@3x.png │ │ └── Contents.json │ ├── nsfw_icon.imageset │ │ ├── nsfw-icon-26-removebg-preview.png │ │ ├── nsfw-icon-26-removebg-preview-1.png │ │ ├── nsfw-icon-26-removebg-preview-2.png │ │ └── Contents.json │ ├── bookmark_icon.imageset │ │ ├── icons8-nastro-segnalibro-90.png │ │ ├── icons8-nastro-segnalibro-90@2x.png │ │ ├── icons8-nastro-segnalibro-90@3x.png │ │ └── Contents.json │ ├── verified_icon.imageset │ │ ├── icons8-account-verificato-150.png │ │ ├── icons8-account-verificato-150@2x.png │ │ ├── icons8-account-verificato-150@3x.png │ │ └── Contents.json │ ├── close_icon.imageset │ │ ├── icons8-chiudi-la-finestra-96_white-1.png │ │ ├── icons8-chiudi-la-finestra-96_white-2.png │ │ ├── icons8-chiudi-la-finestra-96_white.png │ │ └── Contents.json │ ├── default_grey.colorset │ │ └── Contents.json │ ├── default_orange.colorset │ │ └── Contents.json │ ├── default_text.colorset │ │ └── Contents.json │ ├── default_background.colorset │ │ └── Contents.json │ └── default_tab_background.colorset │ │ └── Contents.json ├── AppIconAlternate │ ├── AppIconBase.png │ ├── AppIconBase2.png │ ├── AppIconBase3.png │ ├── AppIconBase4.png │ ├── AppIconDuet.png │ ├── AppIconSport.png │ ├── DarkIcon@1x.png │ ├── DarkIcon@2x.png │ ├── DarkIcon@3x.png │ ├── AppIconArmony.png │ ├── AppIconBase2@2x.png │ ├── AppIconBase2@3x.png │ ├── AppIconBase3@2x.png │ ├── AppIconBase3@3x.png │ ├── AppIconBase4@2x.png │ ├── AppIconBase4@3x.png │ ├── AppIconBase@2x.png │ ├── AppIconBase@3x.png │ ├── AppIconDevelop.png │ ├── AppIconDuet@2x.png │ ├── AppIconDuet@3x.png │ ├── AppIconSphere.png │ ├── AppIconSport@2x.png │ ├── AppIconSport@3x.png │ ├── AppIconArmony@2x.png │ ├── AppIconArmony@3x.png │ ├── AppIconDevelop@2x.png │ ├── AppIconDevelop@3x.png │ ├── AppIconSphere@2x.png │ ├── AppIconSphere@3x.png │ ├── AppIconDevelopPremium.png │ ├── AppIconDevelopPremium@2x.png │ └── AppIconDevelopPremium@3x.png ├── Controllers │ ├── TabBarView │ │ ├── TabBarCoordinator.swift │ │ ├── TabBarViewControllerDelegate.swift │ │ └── TabBarViewController.swift │ ├── Home │ │ ├── HomeViewDelegate.swift │ │ └── HomeViewCoordinator.swift │ ├── CategoriesView │ │ ├── CategoriesViewDelegate.swift │ │ ├── CategoriesViewCoordinator.swift │ │ └── CategoriesViewController.swift │ ├── StarsView │ │ ├── StarsViewControllerDelegate.swift │ │ └── StarsViewCoordinator.swift │ ├── Cells │ │ ├── TitleCell │ │ │ ├── TitleCollectionViewCell.swift │ │ │ └── TitleCollectionViewCell.xib │ │ ├── ImageCell │ │ │ ├── ImageCollectionViewCell.swift │ │ │ └── ImageCollectionViewCell.xib │ │ ├── ToggleCell │ │ │ ├── ToggleCollectionViewCell.swift │ │ │ └── ToggleCollectionViewCell.xib │ │ ├── NavigationButton │ │ │ ├── NavigationButtonCollectionViewCell.swift │ │ │ └── NavigationButtonCollectionViewCell.xib │ │ ├── StarCell │ │ │ ├── StarCollectionViewCell.swift │ │ │ └── StarCollectionViewCell.xib │ │ ├── BannerCell │ │ │ ├── BannerCollectionViewCell.swift │ │ │ └── BannerCollectionViewCell.xib │ │ ├── VideoCell │ │ │ └── VideoCollectionViewCell.swift │ │ ├── StarCarouselCell │ │ │ ├── StarsCarouselCollectionViewCell.swift │ │ │ └── StarsCarouselCollectionViewCell.xib │ │ └── TitleSectionHeader │ │ │ └── TitleSectionHeaderReusableView.swift │ ├── ReelsView │ │ └── ReelsViewControllerDelegate.swift │ ├── StarView │ │ ├── StarViewControllerDelegate.swift │ │ └── StarViewCoordinator.swift │ ├── LeftImageCaption │ │ └── LeftImageCaptionTableViewCell.swift │ ├── WebView │ │ └── WebViewController.swift │ ├── IconSelectionView │ │ └── IconSelectionViewController.swift │ ├── FakeView │ │ └── FakeViewController.swift │ ├── ReelSourceSelection │ │ └── ReelSourceSelectionViewController.swift │ ├── SettingsView │ │ └── SettingsViewController.swift │ └── BookmarksView │ │ └── BookmarksViewController.swift ├── Models │ ├── CategoriesModel.swift │ ├── ErrorResponse.swift │ ├── ReelElement.swift │ ├── PokemonList.swift │ ├── ImagesResponse.swift │ ├── StarsModel.swift │ ├── FeedsResponse.swift │ ├── TikPornResponse.swift │ ├── VideosResponseModel.swift │ └── TikResponse.swift ├── Services │ ├── APIServiceError.swift │ └── UserPreferences.swift ├── Extensions │ ├── BaseNavigationController.swift │ ├── UIScreen+Extensions.swift.swift │ ├── UIViewController+Extensions.swift │ ├── Notification+Extensions.swift │ ├── FullWidthCollectionViewCell.swift │ ├── Date+Extensions.swift │ ├── ColorLayout.swift │ ├── Double+Extensions.swift │ ├── UIView+Extensions.swift │ ├── UICollectionView+Extensions.swift │ ├── UITapGestureRecognizer+Extensions.swift │ ├── BaseViewController.swift │ ├── IconTextView.swift │ └── String+Extensions.swift ├── Base.lproj │ └── LaunchScreen.storyboard ├── SceneDelegate.swift ├── AppDelegate.swift └── Info.plist ├── Podfile ├── LICENSE.md ├── Podfile.lock ├── README.md └── .gitignore /Images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/Images/logo.png -------------------------------------------------------------------------------- /Images/IMG_0690.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/Images/IMG_0690.PNG -------------------------------------------------------------------------------- /Images/IMG_0691.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/Images/IMG_0691.PNG -------------------------------------------------------------------------------- /Images/IMG_0692.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/Images/IMG_0692.PNG -------------------------------------------------------------------------------- /Images/IMG_0693.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/Images/IMG_0693.PNG -------------------------------------------------------------------------------- /Images/IMG_0694.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/Images/IMG_0694.PNG -------------------------------------------------------------------------------- /Images/IMG_0696.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/Images/IMG_0696.PNG -------------------------------------------------------------------------------- /Images/IMG_0697.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/Images/IMG_0697.PNG -------------------------------------------------------------------------------- /Images/IMG_1234123.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/Images/IMG_1234123.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase2.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase3.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase4.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconDuet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconDuet.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconSport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconSport.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/DarkIcon@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/DarkIcon@1x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/DarkIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/DarkIcon@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/DarkIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/DarkIcon@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconArmony.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconArmony.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase2@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase2@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase2@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase3@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase3@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase3@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase4@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase4@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase4@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconBase@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconBase@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconDevelop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconDevelop.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconDuet@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconDuet@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconDuet@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconDuet@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconSphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconSphere.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconSport@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconSport@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconSport@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconSport@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconArmony@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconArmony@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconArmony@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconArmony@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconDevelop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconDevelop@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconDevelop@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconDevelop@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconSphere@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconSphere@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconSphere@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconSphere@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconDevelopPremium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconDevelopPremium.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconDevelopPremium@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconDevelopPremium@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/AppIconAlternate/AppIconDevelopPremium@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/AppIconAlternate/AppIconDevelopPremium@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/header_logo.imageset/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/header_logo.imageset/logo.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/header_logo.imageset/logo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/header_logo.imageset/logo-1.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/header_logo.imageset/logo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/header_logo.imageset/logo-2.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/user_icon.imageset/icons8-user-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/user_icon.imageset/icons8-user-64.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/user_icon.imageset/icons8-user-65.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/user_icon.imageset/icons8-user-65.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/user_icon.imageset/icons8-user-66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/user_icon.imageset/icons8-user-66.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/star_icon.imageset/icons8-stella-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/star_icon.imageset/icons8-stella-90.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/back_icon.imageset/icons8-indietro-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/back_icon.imageset/icons8-indietro-90.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/like_icon.imageset/icons8-mi-piace-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/like_icon.imageset/icons8-mi-piace-90.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/search_icon.imageset/icons8-ricerca-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/search_icon.imageset/icons8-ricerca-50.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/search_icon.imageset/icons8-ricerca-51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/search_icon.imageset/icons8-ricerca-51.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/search_icon.imageset/icons8-ricerca-52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/search_icon.imageset/icons8-ricerca-52.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/star_icon.imageset/icons8-stella-90@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/star_icon.imageset/icons8-stella-90@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/star_icon.imageset/icons8-stella-90@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/star_icon.imageset/icons8-stella-90@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/views_icon.imageset/icons8-visibile-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/views_icon.imageset/icons8-visibile-90.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/audio_on.imageset/icons8-volume-alto-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/audio_on.imageset/icons8-volume-alto-100.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/back_icon.imageset/icons8-indietro-90@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/back_icon.imageset/icons8-indietro-90@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/back_icon.imageset/icons8-indietro-90@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/back_icon.imageset/icons8-indietro-90@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/like_icon.imageset/icons8-mi-piace-90@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/like_icon.imageset/icons8-mi-piace-90@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/like_icon.imageset/icons8-mi-piace-90@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/like_icon.imageset/icons8-mi-piace-90@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/top_arrow.imageset/icons8-doppio-sù-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/top_arrow.imageset/icons8-doppio-sù-100.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/top_arrow.imageset/icons8-doppio-sù-101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/top_arrow.imageset/icons8-doppio-sù-101.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/top_arrow.imageset/icons8-doppio-sù-102.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/top_arrow.imageset/icons8-doppio-sù-102.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/views_icon.imageset/icons8-visibile-90@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/views_icon.imageset/icons8-visibile-90@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/views_icon.imageset/icons8-visibile-90@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/views_icon.imageset/icons8-visibile-90@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/audio_off.imageset/icons8-nessun-audio-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/audio_off.imageset/icons8-nessun-audio-100.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/audio_on.imageset/icons8-volume-alto-100@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/audio_on.imageset/icons8-volume-alto-100@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/audio_on.imageset/icons8-volume-alto-100@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/audio_on.imageset/icons8-volume-alto-100@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/home_icon.imageset/icons8-home-page-90 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/home_icon.imageset/icons8-home-page-90 (1).png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/audio_off.imageset/icons8-nessun-audio-100@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/audio_off.imageset/icons8-nessun-audio-100@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/audio_off.imageset/icons8-nessun-audio-100@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/audio_off.imageset/icons8-nessun-audio-100@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/categories_icon.imageset/icons8-categoria-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/categories_icon.imageset/icons8-categoria-60.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/external_icon.imageset/icons8-link-esterno-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/external_icon.imageset/icons8-link-esterno-60.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/external_icon.imageset/icons8-link-esterno-61.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/external_icon.imageset/icons8-link-esterno-61.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/external_icon.imageset/icons8-link-esterno-62.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/external_icon.imageset/icons8-link-esterno-62.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/home_icon.imageset/icons8-home-page-90 (1)@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/home_icon.imageset/icons8-home-page-90 (1)@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/home_icon.imageset/icons8-home-page-90 (1)@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/home_icon.imageset/icons8-home-page-90 (1)@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/reels_icon.imageset/icons8-instagram-reels-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/reels_icon.imageset/icons8-instagram-reels-100.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/settings_icon.imageset/icons8-impostazioni-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/settings_icon.imageset/icons8-impostazioni-120.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/categories_icon.imageset/icons8-categoria-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/categories_icon.imageset/icons8-categoria-60@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/categories_icon.imageset/icons8-categoria-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/categories_icon.imageset/icons8-categoria-60@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/nsfw_icon.imageset/nsfw-icon-26-removebg-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/nsfw_icon.imageset/nsfw-icon-26-removebg-preview.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/bookmark_icon.imageset/icons8-nastro-segnalibro-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/bookmark_icon.imageset/icons8-nastro-segnalibro-90.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/nsfw_icon.imageset/nsfw-icon-26-removebg-preview-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/nsfw_icon.imageset/nsfw-icon-26-removebg-preview-1.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/nsfw_icon.imageset/nsfw-icon-26-removebg-preview-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/nsfw_icon.imageset/nsfw-icon-26-removebg-preview-2.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/reels_icon.imageset/icons8-instagram-reels-100@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/reels_icon.imageset/icons8-instagram-reels-100@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/reels_icon.imageset/icons8-instagram-reels-100@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/reels_icon.imageset/icons8-instagram-reels-100@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/settings_icon.imageset/icons8-impostazioni-120@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/settings_icon.imageset/icons8-impostazioni-120@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/settings_icon.imageset/icons8-impostazioni-120@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/settings_icon.imageset/icons8-impostazioni-120@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/bookmark_icon.imageset/icons8-nastro-segnalibro-90@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/bookmark_icon.imageset/icons8-nastro-segnalibro-90@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/bookmark_icon.imageset/icons8-nastro-segnalibro-90@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/bookmark_icon.imageset/icons8-nastro-segnalibro-90@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/verified_icon.imageset/icons8-account-verificato-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/verified_icon.imageset/icons8-account-verificato-150.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/close_icon.imageset/icons8-chiudi-la-finestra-96_white-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/close_icon.imageset/icons8-chiudi-la-finestra-96_white-1.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/close_icon.imageset/icons8-chiudi-la-finestra-96_white-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/close_icon.imageset/icons8-chiudi-la-finestra-96_white-2.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/close_icon.imageset/icons8-chiudi-la-finestra-96_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/close_icon.imageset/icons8-chiudi-la-finestra-96_white.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/verified_icon.imageset/icons8-account-verificato-150@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/verified_icon.imageset/icons8-account-verificato-150@2x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/verified_icon.imageset/icons8-account-verificato-150@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnonsDeveloper/icomeout-pornhub-iOS/HEAD/ICO-Visualizer/Assets.xcassets/verified_icon.imageset/icons8-account-verificato-150@3x.png -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/TabBarView/TabBarCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabBarCoordinator.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 24/09/21. 6 | // 7 | 8 | import Foundation 9 | 10 | class TabBarCoordinator { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Home/HomeViewDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeViewDelegate.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol HomeViewDelegate{ 12 | func reloadView() 13 | func showError(message: String) 14 | } 15 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/CategoriesModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CategoriesModel.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - ErrorResponse 12 | struct CategoriesModel: Codable { 13 | let categories: [Category] 14 | } 15 | 16 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/CategoriesView/CategoriesViewDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchViewDelegate.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol CategoriesViewDelegate{ 12 | func reloadView() 13 | func onError(message: Error) 14 | } 15 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/ErrorResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ErrorResponse.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - ErrorResponse 12 | public struct ErrorResponse: Codable { 13 | let code, message: String 14 | let example: String 15 | } 16 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/TabBarView/TabBarViewControllerDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabBarViewControllerDelegate.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 24/09/21. 6 | // 7 | 8 | import Foundation 9 | 10 | protocol TabBarViewControllerDelegate { 11 | func setPage(index: Int) 12 | func searchForCategory(category: String) 13 | func setHeader() 14 | } 15 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/StarsView/StarsViewControllerDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StarsViewControllerDelegate.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol StarsViewControllerDelegate{ 12 | func reloadView() 13 | func onError(error: Error) 14 | } 15 | -------------------------------------------------------------------------------- /ICO-Visualizer/Services/APIServiceError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // APIServiceError.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum APIServiceError: Error { 12 | case unknown 13 | case decodeError(Error) 14 | case noDataFound 15 | case error(ErrorResponse) 16 | } 17 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/default_grey.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.502", 9 | "green" : "0.502", 10 | "red" : "0.502" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/default_orange.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.000", 9 | "green" : "0.647", 10 | "red" : "1.000" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/default_text.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "1.000", 9 | "green" : "1.000", 10 | "red" : "1.000" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/default_background.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.106", 9 | "green" : "0.106", 10 | "red" : "0.106" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/default_tab_background.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.161", 9 | "green" : "0.161", 10 | "red" : "0.161" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/TitleCell/TitleCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TitleCollectionViewCell.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TitleCollectionViewCell: FullWidthCollectionViewCell { 12 | 13 | @IBOutlet weak var titleLabel: UILabel! 14 | 15 | func setup(title: String){ 16 | self.titleLabel.text = title 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/ReelsView/ReelsViewControllerDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReelsViewControllerDelegate.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 10/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol ReelsViewControllerDelegate { 12 | func reloadView(newIndexs: [IndexPath]) 13 | func reloadCollection() 14 | func openUrl(url: URL) 15 | func switchSound() 16 | func openWebView(title: String, url: String) 17 | } 18 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/BaseNavigationController.swift: -------------------------------------------------------------------------------- 1 | 2 | 3 | import UIKit 4 | 5 | class BaseNavigationController : UINavigationController{ 6 | override func viewDidLoad() { 7 | super.viewDidLoad() 8 | self.interactivePopGestureRecognizer?.delegate = self 9 | } 10 | } 11 | 12 | extension BaseNavigationController : UIGestureRecognizerDelegate{ 13 | func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 14 | return viewControllers.count > 0 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'ICO-visualizer' do 5 | # Comment the next line if you don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for ICO-visualizer 9 | pod 'Alamofire' 10 | pod 'SDWebImage' 11 | pod 'ImageViewer.swift', '~> 3.0' 12 | pod 'ImageViewer.swift/Fetcher', '~> 3.0' 13 | pod 'CCBottomRefreshControl' 14 | pod 'SVPinView', '~> 1.0' 15 | pod 'AlamofireNetworkActivityLogger' 16 | end 17 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/header_logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "logo.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "logo-1.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "logo-2.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/StarView/StarViewControllerDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StarViewControllerDelegate.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 04/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol StarViewControllerDelegate{ 12 | var videosCompleted: Bool {get set} 13 | func reloadView(_ message: String?) 14 | func reloadImages(_ message: String?) 15 | func getStar() -> Star 16 | func setupErrorMessage(message: String) 17 | } 18 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/user_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-user-64.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-user-65.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-user-66.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/ReelElement.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReelElement.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 15/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct ReelElement { 12 | let videoUrl: String? 13 | let username: String? 14 | let avatarUrl: String? 15 | let likes: Int? 16 | let views: Int? 17 | let tags: [String]? 18 | let verified: Bool? 19 | let externalUrl: String? 20 | let duration: Int? 21 | let width, height: Int? 22 | } 23 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/nsfw_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "nsfw-icon-26-removebg-preview.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "nsfw-icon-26-removebg-preview-1.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "nsfw-icon-26-removebg-preview-2.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/ImageCell/ImageCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageCollectionViewCell.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 08/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class ImageCollectionViewCell: UICollectionViewCell { 13 | @IBOutlet weak var imageView: UIImageView! 14 | 15 | func setup(imageUrl: String){ 16 | self.imageView.clipsToBounds = true 17 | self.imageView.sd_setImage(with: URL(string: imageUrl)!, completed: nil) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/search_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-ricerca-50.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-ricerca-51.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-ricerca-52.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/star_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-stella-90.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-stella-90@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-stella-90@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/back_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-indietro-90.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-indietro-90@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-indietro-90@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/like_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-mi-piace-90.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-mi-piace-90@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-mi-piace-90@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/top_arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-doppio-sù-100.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-doppio-sù-101.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-doppio-sù-102.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/views_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-visibile-90.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-visibile-90@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-visibile-90@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/audio_on.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-volume-alto-100.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-volume-alto-100@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-volume-alto-100@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/categories_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-categoria-60.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-categoria-60@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-categoria-60@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/external_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-link-esterno-60.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-link-esterno-61.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-link-esterno-62.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/audio_off.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-nessun-audio-100.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-nessun-audio-100@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-nessun-audio-100@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/home_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-home-page-90 (1).png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-home-page-90 (1)@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-home-page-90 (1)@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/settings_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-impostazioni-120.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-impostazioni-120@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-impostazioni-120@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/reels_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-instagram-reels-100.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-instagram-reels-100@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-instagram-reels-100@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/bookmark_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-nastro-segnalibro-90.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-nastro-segnalibro-90@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-nastro-segnalibro-90@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/verified_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-account-verificato-150.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-account-verificato-150@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-account-verificato-150@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/close_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icons8-chiudi-la-finestra-96_white.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "icons8-chiudi-la-finestra-96_white-1.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "icons8-chiudi-la-finestra-96_white-2.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/PokemonList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PokemonList.swift 3 | // pokemon-visualizer 4 | // 5 | // Created by Anonymous on 26/10/21. 6 | // 7 | 8 | import Foundation 9 | 10 | // MARK: - PokemonList 11 | struct PokemonList: Codable { 12 | let count: Int? 13 | var results: [PokemonListResult] 14 | } 15 | 16 | // MARK: - Result 17 | struct PokemonListResult: Codable { 18 | let name: String? 19 | let url: String? 20 | 21 | var imageUrl: String? { 22 | guard let pokemonId = URL(string: self.url ?? "")?.lastPathComponent else { return nil } 23 | return "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork" + "/\(pokemonId).png" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/UIScreen+Extensions.swift.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScreen+Extensions.swift.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 10/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIScreen { 12 | 13 | public var topSafeAreaHeight: CGFloat { 14 | let window = UIApplication.shared.windows.first 15 | let topPadding = window?.safeAreaInsets.top 16 | return topPadding ?? 0 17 | } 18 | 19 | public var bottomSafeAreaHeight: CGFloat { 20 | let window = UIApplication.shared.windows.first 21 | let bottomPadding = window?.safeAreaInsets.bottom 22 | return bottomPadding ?? 0 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/UIViewController+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Extensions.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 09/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIViewController { 12 | func setupToHideKeyboardOnTapOnView() 13 | { 14 | let tap: UITapGestureRecognizer = UITapGestureRecognizer( 15 | target: self, 16 | action: #selector(UIViewController.dismissKeyboard)) 17 | 18 | tap.cancelsTouchesInView = false 19 | view.addGestureRecognizer(tap) 20 | } 21 | 22 | @objc func dismissKeyboard() 23 | { 24 | view.endEditing(true) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/Notification+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Notification+Extensions.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 09/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Notification.Name { 12 | static let didUpdateBookmarks = Notification.Name("didUpdateBookmarks") 13 | static let didEnterCorrectPin = Notification.Name("didEnterCorrectPin") 14 | static let didEnterFakePin = Notification.Name("didEnterFakePin") 15 | static let didPressVolumeUp = Notification.Name("didPressVolumeUp") 16 | static let didPressVolumeDown = Notification.Name("didPressVolumeDown") 17 | static let didChangeReelPreference = Notification.Name("didChangeReelPreference") 18 | } 19 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/ToggleCell/ToggleCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ToggleCollectionViewCell.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 12/10/21. 6 | // 7 | 8 | import UIKit 9 | 10 | class ToggleCollectionViewCell: FullWidthCollectionViewCell { 11 | @IBOutlet weak var titleView: UILabel! 12 | @IBOutlet weak var switchView: UISwitch! 13 | private var onSwitchStateChanged: ((Bool) -> Void)? 14 | 15 | func setup(title: String, isOn: Bool, onSwitchStateChanged: ((Bool) -> Void)?){ 16 | self.titleView.text = title 17 | self.onSwitchStateChanged = onSwitchStateChanged 18 | self.switchView.setOn(isOn, animated: false) 19 | } 20 | 21 | @IBAction func onSwitchChanged(_ sender: UISwitch) { 22 | onSwitchStateChanged?(sender.isOn) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/ImagesResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImagesResponse.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 16/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - ImagesResponseElement 12 | struct ImagesResponseElement: Codable { 13 | let gURL: String? 14 | let tURL: String? 15 | let h: Int? 16 | let desc: String? 17 | let tURL460: String? 18 | let gid, mid, tid, atid: String? 19 | let nofollow, outLink: Bool? 20 | 21 | enum CodingKeys: String, CodingKey { 22 | case gURL = "g_url" 23 | case tURL = "t_url" 24 | case h, desc 25 | case tURL460 = "t_url_460" 26 | case gid, mid, tid, atid, nofollow, outLink 27 | } 28 | } 29 | 30 | typealias ImagesResponse = [ImagesResponseElement] 31 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/FullWidthCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FullWidthCollectionViewCell.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 21/09/21. 6 | // 7 | 8 | import UIKit 9 | 10 | 11 | class FullWidthCollectionViewCell: UICollectionViewCell { 12 | override func systemLayoutSizeFitting( 13 | _ targetSize: CGSize, 14 | withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, 15 | verticalFittingPriority: UILayoutPriority) -> CGSize { 16 | 17 | var targetSize = targetSize 18 | targetSize.height = CGFloat.greatestFiniteMagnitude 19 | 20 | let size = super.systemLayoutSizeFitting( 21 | targetSize, 22 | withHorizontalFittingPriority: .required, 23 | verticalFittingPriority: .fittingSizeLevel 24 | ) 25 | return size 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/NavigationButton/NavigationButtonCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationButtonViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 28/09/21. 6 | // 7 | 8 | import UIKit 9 | 10 | class NavigationButtonCollectionViewCell: FullWidthCollectionViewCell { 11 | @IBOutlet weak var tapView: UIView! 12 | @IBOutlet weak var titleView: UILabel! 13 | 14 | private var tapAction: (() -> Void)? 15 | 16 | func setup(title: String, onTap: (() -> Void)?){ 17 | self.titleView.text = title 18 | self.tapAction = onTap 19 | tapView.isUserInteractionEnabled = true 20 | let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:))) 21 | tapView.addGestureRecognizer(tap) 22 | } 23 | 24 | @objc func handleTap(_ sender: UITapGestureRecognizer? = nil) { 25 | self.tapAction?() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/Date+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Date+Extensions.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 09/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension Date { 12 | func timeAgo() -> String { 13 | let formatter = DateComponentsFormatter() 14 | formatter.unitsStyle = .full 15 | formatter.allowedUnits = [.year, .month, .day, .hour, .minute, .second] 16 | formatter.zeroFormattingBehavior = .dropAll 17 | formatter.maximumUnitCount = 1 18 | return String(format: formatter.string(from: self, to: Date()) ?? "", locale: .current) + " ago" 19 | } 20 | 21 | func localTime() -> Date { 22 | let timezone = TimeZone.current 23 | let seconds = TimeInterval(timezone.secondsFromGMT(for: self)) 24 | return Date(timeInterval: seconds, since: self) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/StarsModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StarsModel.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - Stars 12 | struct StarsModel: Codable { 13 | var stars: [StarElement]? 14 | } 15 | 16 | // MARK: - StarElement 17 | struct StarElement: Codable { 18 | var star: Star? 19 | } 20 | 21 | // MARK: - StarStar 22 | struct Star: Codable { 23 | var starName: String? 24 | var starThumb: String? 25 | var starURL: String? 26 | var gender: String? 27 | var videosCountAll: String? 28 | var starVideos: [Video]? 29 | 30 | enum CodingKeys: String, CodingKey { 31 | case starName = "star_name" 32 | case starThumb = "star_thumb" 33 | case starURL = "star_url" 34 | case gender 35 | case videosCountAll = "videos_count_all" 36 | case starVideos 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/StarCell/StarCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StarCollectionViewCell.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SDWebImage 11 | 12 | class StarCollectionViewCell: UICollectionViewCell { 13 | @IBOutlet weak var thumbImageView: UIImageView! 14 | @IBOutlet weak var titleLabel: UILabel! 15 | @IBOutlet weak var backgroundCellView: UIView! 16 | @IBOutlet weak var bookmarkIcon: UIImageView! 17 | 18 | func setup(star: Star){ 19 | backgroundCellView.setShadowAndCorner(cornerRadius: 8) 20 | if let thumbUrl = star.starThumb{ 21 | thumbImageView.sd_setImage(with: URL(string: thumbUrl)!, completed: nil) 22 | } 23 | titleLabel.text = star.starName 24 | bookmarkIcon.isHidden = !UserBookmakrs.shared.checkStarBookmarksCointain(star) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/ColorLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorLayout.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ColorLayout { 12 | static let default_background: UIColor = UIColor(named: "default_background") ?? .black 13 | static let default_tab_background: UIColor = UIColor(named: "default_tab_background") ?? .darkGray 14 | static let default_orange: UIColor = UIColor(named: "default_orange") ?? .systemOrange 15 | static let default_grey: UIColor = UIColor(named: "default_grey") ?? .lightGray 16 | static let default_text: UIColor = UIColor(named: "default_text") ?? .white 17 | } 18 | 19 | class ContentLayout { 20 | public static var safeAreaTopHeight: CGFloat { 21 | let window = UIApplication.shared.windows.first 22 | return window?.safeAreaInsets.top ?? 0 23 | } 24 | 25 | public static var safeAreaBottomHeight: CGFloat { 26 | let window = UIApplication.shared.windows.first 27 | return window?.safeAreaInsets.bottom ?? 0 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 AnonsDeveloper 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/BannerCell/BannerCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BannerCollectionViewCell.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 28/09/21. 6 | // 7 | 8 | import UIKit 9 | 10 | class BannerCollectionViewCell: FullWidthCollectionViewCell { 11 | @IBOutlet weak var backgroundViewCell: UIView! 12 | @IBOutlet weak var textLabel: UILabel! 13 | private var onTap: (() -> Void)? 14 | 15 | func setup(text: String, onTap: (() -> Void)? = nil){ 16 | backgroundViewCell.setShadowAndCorner(cornerRadius: 8) 17 | self.onTap = onTap 18 | self.textLabel.text = text 19 | let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:))) 20 | self.backgroundViewCell.addGestureRecognizer(tap) 21 | self.backgroundViewCell.isUserInteractionEnabled = true 22 | } 23 | 24 | @objc func handleTap(_ sender: UITapGestureRecognizer? = nil) { 25 | onTap?() 26 | } 27 | 28 | func setup(text: NSMutableAttributedString){ 29 | backgroundViewCell.setShadowAndCorner(cornerRadius: 8) 30 | self.textLabel.attributedText = text 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/Double+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Double+Extensions.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 09/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Double { 12 | var shortStringRepresentation: String { 13 | if self.isNaN { 14 | return "NaN" 15 | } 16 | if self.isInfinite { 17 | return "\(self < 0.0 ? "-" : "+")Infinity" 18 | } 19 | let units = ["", "k", "M"] 20 | var interval = self 21 | var i = 0 22 | while i < units.count - 1 { 23 | if abs(interval) < 1000.0 { 24 | break 25 | } 26 | i += 1 27 | interval /= 1000.0 28 | } 29 | // + 2 to have one digit after the comma, + 1 to not have any. 30 | // Remove the * and the number of digits argument to display all the digits after the comma. 31 | let val = log10(abs(interval)) 32 | if val.isNaN || val.isInfinite { 33 | return "0" 34 | } 35 | return "\(String(format: "%0.*g", Int(val) + 2, interval))\(units[i])" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (5.4.4) 3 | - AlamofireNetworkActivityLogger (3.4.0): 4 | - Alamofire (~> 5.4.0) 5 | - CCBottomRefreshControl (0.5.2) 6 | - ImageViewer.swift (3.3.3) 7 | - ImageViewer.swift/Fetcher (3.3.3): 8 | - SDWebImage 9 | - SDWebImage (5.12.1): 10 | - SDWebImage/Core (= 5.12.1) 11 | - SDWebImage/Core (5.12.1) 12 | - SVPinView (1.0.11) 13 | 14 | DEPENDENCIES: 15 | - Alamofire 16 | - AlamofireNetworkActivityLogger 17 | - CCBottomRefreshControl 18 | - ImageViewer.swift (~> 3.0) 19 | - ImageViewer.swift/Fetcher (~> 3.0) 20 | - SDWebImage 21 | - SVPinView (~> 1.0) 22 | 23 | SPEC REPOS: 24 | trunk: 25 | - Alamofire 26 | - AlamofireNetworkActivityLogger 27 | - CCBottomRefreshControl 28 | - ImageViewer.swift 29 | - SDWebImage 30 | - SVPinView 31 | 32 | SPEC CHECKSUMS: 33 | Alamofire: f3b09a368f1582ab751b3fff5460276e0d2cf5c9 34 | AlamofireNetworkActivityLogger: 162ab8aee00e6267a4304d7cc134e13ccfe3bcc5 35 | CCBottomRefreshControl: 389780b4488321c91d18f66a6da5ef9606df6de5 36 | ImageViewer.swift: 3dbb74a68ac4bdd6cdd585b3128dae17ccd733e5 37 | SDWebImage: 4dc3e42d9ec0c1028b960a33ac6b637bb432207b 38 | SVPinView: 9b538d0ba68cdb092afe4f0f67ec84cbed079466 39 | 40 | PODFILE CHECKSUM: ad785374689f0733789fc91f5c288c453adec453 41 | 42 | COCOAPODS: 1.11.2 43 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/UIView+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extensions.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 21/09/21. 6 | // 7 | 8 | import UIKit 9 | 10 | extension UIView { 11 | class var className: String { 12 | return String(describing: self) 13 | } 14 | 15 | func setShadowAndCorner(cornerRadius: CGFloat){ 16 | self.layer.shadowColor = UIColor.black.cgColor 17 | self.layer.shadowOpacity = 0.4 18 | self.layer.shadowOffset = .zero 19 | self.layer.shadowRadius = 10 20 | self.layer.cornerRadius = cornerRadius 21 | } 22 | 23 | func calculateLabelHeightForText(text:String, font:UIFont, width:CGFloat) -> CGFloat{ 24 | let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude)) 25 | label.numberOfLines = 0 26 | label.lineBreakMode = NSLineBreakMode.byWordWrapping 27 | label.font = font 28 | label.text = text 29 | 30 | label.sizeToFit() 31 | return label.frame.height 32 | } 33 | } 34 | 35 | extension Optional where Wrapped == String { 36 | var nilOrEmpty: Bool { 37 | if self == nil { 38 | return true 39 | } 40 | if self == ""{ 41 | return true 42 | } 43 | return false 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ICO-Visualizer/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/CategoriesView/CategoriesViewCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchViewCoordinator.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class CategoriesViewCoordinator { 12 | 13 | public var categories: [Category] = [] 14 | 15 | private var allCategories: [Category] = [] 16 | 17 | private var delegate: CategoriesViewDelegate! 18 | 19 | public var filter: String = "" 20 | 21 | init(_ delegate: CategoriesViewDelegate) { 22 | self.delegate = delegate 23 | } 24 | 25 | func loadData(){ 26 | self.categories = [] 27 | self.allCategories = [] 28 | APIService.shared.fetchCategories { result in 29 | switch result { 30 | case .success(let categories): 31 | self.categories = categories.categories 32 | self.allCategories = categories.categories 33 | self.delegate.reloadView() 34 | case .failure(let error): 35 | print(error) 36 | } 37 | } 38 | } 39 | 40 | func filterCategories(filter: String){ 41 | self.filter = filter 42 | if filter == "" { 43 | self.categories = allCategories 44 | DispatchQueue.main.async { 45 | self.delegate.reloadView() 46 | } 47 | } 48 | else{ 49 | let filtered = allCategories.filter( { $0.category?.capitalizingFirstLetter().replacingOccurrences(of: "-", with: " ").lowercased().contains(filter.lowercased()) ?? false } ) 50 | self.categories = filtered 51 | DispatchQueue.main.async { 52 | self.delegate.reloadView() 53 | } 54 | } 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | iCome Out is an open source project of an unofficial Pornub app for iPhone and iPad, written in Swift with some cool features 6 | 7 | ## Getting Started 8 | 9 | ### Prerequisites 10 | 11 | - iOS 13.5+ 12 | - XCode 13 | 14 | ### Installation 15 | 16 | - Clone the repo 17 | - run `pod install` from the terminal, on the root of the project 18 | - build with XCode on your device 19 | 20 | ## Features 21 | ⚠️ - Adult Content - ⚠️ 22 | 23 | *some screenshots have been partially censored* 24 | 25 | ### New Reels section and enanched graphics! 26 | #### You can choose the reels source from the settings 27 | 28 | ⬆️ available in tag 1.3 29 | 30 | ### PIN protection 31 | 32 | 33 | ### Homepage with a search field for the videos and categories filter 34 | 35 | 36 | ### List of all stars with details 37 | 38 | 39 | ### Save your favourite videos and star to your bookmarks 40 | 41 | 42 | ### Extra features: 43 | - Setup a fake PIN, with this feature if you put your fake PIN on the access screen a simple Pokemon list will appear, just for your privacy ;) 44 | - Change the App Icon to hide the app better 45 | - FaceID/TouchID authentication 46 | 47 | ## Authors 48 | 49 | * 🤫 50 | 51 | ## License 52 | 53 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 54 | 55 | ##### Known issues 56 | - Sometimes the video preview does not load correctly, just close and reopen the preview 57 | - Sometimes the app crash on loading Stars list 58 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/UICollectionView+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UICollectionView+Extensions.swift 3 | // Circular 4 | // 5 | // Created by Anonymous on 15/07/2020. 6 | // Copyright © 2020 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UICollectionView { 13 | func register(cellType cell: UICollectionViewCell.Type) { 14 | self.register(UINib(nibName: cell.className, bundle: nil), forCellWithReuseIdentifier: cell.className) 15 | } 16 | 17 | func setupView(_ fromView: T) where T: UICollectionViewDataSource, T: UICollectionViewDelegate { 18 | self.delegate = fromView 19 | self.dataSource = fromView 20 | let layout = self.collectionViewLayout 21 | if let flowLayout = layout as? UICollectionViewFlowLayout { 22 | flowLayout.estimatedItemSize = CGSize( 23 | width: UIScreen.main.bounds.width, 24 | height: 200 25 | ) 26 | } 27 | self.register(cellType: VideoCollectionViewCell.self) 28 | self.register(cellType: TitleCollectionViewCell.self) 29 | self.register(cellType: StarCollectionViewCell.self) 30 | self.register(cellType: BannerCollectionViewCell.self) 31 | self.register(cellType: NavigationButtonCollectionViewCell.self) 32 | self.register(cellType: ToggleCollectionViewCell.self) 33 | self.register(cellType: StarsCarouselCollectionViewCell.self) 34 | self.register(cellType: ImageCollectionViewCell.self) 35 | self.register(cellType: ReelCollectionViewCell.self) 36 | self.register(LeftImageCaptionTableViewCell.self, forCellWithReuseIdentifier: LeftImageCaptionTableViewCell.className) 37 | self.register(TitleSectionHeaderReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: TitleSectionHeaderReusableView.className) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/UITapGestureRecognizer+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITapGestureRecognizer+Extensions.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 09/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UITapGestureRecognizer { 12 | func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool { 13 | // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage 14 | let layoutManager = NSLayoutManager() 15 | let textContainer = NSTextContainer(size: CGSize.zero) 16 | let textStorage = NSTextStorage(attributedString: label.attributedText!) 17 | 18 | // Configure layoutManager and textStorage 19 | layoutManager.addTextContainer(textContainer) 20 | textStorage.addLayoutManager(layoutManager) 21 | 22 | // Configure textContainer 23 | textContainer.lineFragmentPadding = 0.0 24 | textContainer.lineBreakMode = label.lineBreakMode 25 | textContainer.maximumNumberOfLines = label.numberOfLines 26 | let labelSize = label.bounds.size 27 | textContainer.size = labelSize 28 | 29 | // Find the tapped character location and compare it to the specified range 30 | let locationOfTouchInLabel = self.location(in: label) 31 | let textBoundingBox = layoutManager.usedRect(for: textContainer) 32 | 33 | let textContainerOffset = CGPoint(x: (labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, y: (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y) 34 | 35 | let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, y: locationOfTouchInLabel.y - textContainerOffset.y) 36 | let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) 37 | return NSLocationInRange(indexOfCharacter, targetRange) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/VideoCell/VideoCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoCollectionViewCell.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SDWebImage 11 | 12 | class VideoCollectionViewCell: FullWidthCollectionViewCell { 13 | @IBOutlet weak var thumbImageView: UIImageView! 14 | @IBOutlet weak var titleLabel: UILabel! 15 | @IBOutlet weak var backgroundCellView: UIView! 16 | @IBOutlet weak var viewsLabel: UILabel! 17 | @IBOutlet weak var starLabel: UILabel! 18 | @IBOutlet weak var durationLabel: UILabel! 19 | 20 | @IBOutlet weak var gradientView: UIView! 21 | @IBOutlet weak var bookmarkIcon: UIImageView! 22 | 23 | let gradient: CAGradientLayer = { 24 | return CAGradientLayer() 25 | }() 26 | 27 | func setup(video: Video){ 28 | backgroundCellView.setShadowAndCorner(cornerRadius: 8) 29 | if let thumbUrl = video.thumb{ 30 | thumbImageView.sd_setImage(with: URL(string: thumbUrl)!, completed: nil) 31 | } 32 | titleLabel.text = video.title 33 | viewsLabel.text = "" 34 | var viewsText = "" 35 | if let views = video.views { 36 | viewsText += "\(Double(views).shortStringRepresentation) Views" 37 | } 38 | if let rating = video.rating?.ratingString, let ratingDouble = Double(rating) { 39 | viewsText += " | \(String(format: "%.0f", ratingDouble))%" 40 | } 41 | self.viewsLabel.text = viewsText 42 | self.starLabel.text = video.pornstars?.first?.pornstarName ?? "" 43 | self.durationLabel.text = video.duration ?? "" 44 | bookmarkIcon.isHidden = !UserBookmakrs.shared.checkVideoBookmarksCointain(video) 45 | 46 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { 47 | self.gradient.frame = self.gradientView.bounds 48 | self.gradient.colors = [UIColor.clear.cgColor, UIColor.black.cgColor] 49 | 50 | self.gradientView.layer.insertSublayer(self.gradient, at: 0) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/StarsView/StarsViewCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StarsViewCoordinator.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | import Foundation 9 | 10 | class StarsViewCoordinator { 11 | 12 | public var stars: [StarElement] = [] 13 | 14 | private var allStars: [StarElement] = [] 15 | 16 | private var delegate: StarsViewControllerDelegate! 17 | 18 | init(_ delegate: StarsViewControllerDelegate) { 19 | self.delegate = delegate 20 | } 21 | 22 | func filterStars(filter: String){ 23 | if filter == "" { 24 | self.stars = allStars 25 | DispatchQueue.main.async { 26 | self.delegate.reloadView() 27 | } 28 | } 29 | else{ 30 | let filtered = allStars.filter( { $0.star?.starName?.lowercased().contains(filter.lowercased()) ?? false } ) 31 | self.stars = filtered 32 | DispatchQueue.main.async { 33 | self.delegate.reloadView() 34 | } 35 | } 36 | } 37 | 38 | func loadData(){ 39 | self.allStars = [] 40 | self.stars = [] 41 | DispatchQueue.global(qos: .default).async { 42 | APIService.shared.fetchStars { result in 43 | switch result { 44 | case .success(let stars): 45 | if let stars = stars.stars { 46 | for item in stars { 47 | self.stars.append(item) 48 | } 49 | } 50 | let orderedStars = self.stars.sorted(by: { Int($0.star?.videosCountAll ?? "0") ?? 0 > Int($1.star?.videosCountAll ?? "0") ?? 0 }) 51 | self.stars = orderedStars 52 | self.allStars = self.stars 53 | DispatchQueue.main.async { 54 | self.delegate.reloadView() 55 | } 56 | case .failure(let error): 57 | print(error) 58 | self.delegate.onError(error: error) 59 | } 60 | } 61 | 62 | } 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/StarCarouselCell/StarsCarouselCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StarsCarouselCollectionViewCell.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 05/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class StarsCarouselCollectionViewCell: FullWidthCollectionViewCell { 12 | @IBOutlet weak var collectionView: UICollectionView! 13 | 14 | private var stars: [Star] = [] 15 | 16 | private var onItemSelect: ((IndexPath) -> Void)? 17 | 18 | func setup(stars: [Star], onItemSelect: @escaping (IndexPath) -> Void){ 19 | self.stars = stars 20 | self.onItemSelect = onItemSelect 21 | if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { 22 | flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20) 23 | flowLayout.scrollDirection = .horizontal 24 | flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize 25 | } 26 | collectionView.register(cellType: StarCollectionViewCell.self) 27 | collectionView.delegate = self 28 | collectionView.showsHorizontalScrollIndicator = false 29 | collectionView.showsVerticalScrollIndicator = false 30 | collectionView.dataSource = self 31 | collectionView.backgroundColor = .clear 32 | collectionView.reloadData() 33 | } 34 | } 35 | 36 | extension StarsCarouselCollectionViewCell: UICollectionViewDataSource, UICollectionViewDelegate { 37 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 38 | return self.stars.count 39 | } 40 | 41 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 42 | let starCell = collectionView.dequeueReusableCell(withReuseIdentifier: StarCollectionViewCell.className, for: indexPath) as! StarCollectionViewCell 43 | starCell.setup(star: self.stars[indexPath.row]) 44 | return starCell 45 | } 46 | 47 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 48 | self.onItemSelect?(indexPath) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/TitleSectionHeader/TitleSectionHeaderReusableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TitleSectionHeaderReusableView.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 22/10/21. 6 | // 7 | 8 | import UIKit 9 | 10 | class TitleSectionHeaderReusableView: UICollectionReusableView { 11 | 12 | var titleLabel: UILabel = { 13 | let label = UILabel() 14 | label.custom(title: "Title", font: UIFont(name: "HelveticaNeue-Medium", size:20)!, titleColor: ColorLayout.default_text, textAlignment: .left, numberOfLines: 1) 15 | return label 16 | }() 17 | 18 | override init(frame: CGRect) { 19 | super.init(frame: frame) 20 | setupViews() 21 | setupConstraints() 22 | } 23 | 24 | required init?(coder aDecoder: NSCoder) { 25 | fatalError("init(coder:) has not been implemented") 26 | } 27 | 28 | func setupTitle(title: String){ 29 | titleLabel.text = title 30 | } 31 | } 32 | 33 | extension TitleSectionHeaderReusableView : ViewSetable { 34 | 35 | func setupViews() { 36 | autoresizingMask = [.flexibleWidth, .flexibleHeight] 37 | backgroundColor = ColorLayout.default_background 38 | addSubview(titleLabel) 39 | } 40 | 41 | func setupConstraints() { 42 | titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12).isActive = true 43 | titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 30).isActive = true 44 | titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 30).isActive = true 45 | } 46 | } 47 | 48 | extension UILabel { 49 | 50 | func custom(title: String, font: UIFont, titleColor: UIColor, textAlignment: NSTextAlignment, numberOfLines: Int) { 51 | self.text = title 52 | self.textAlignment = textAlignment 53 | self.font = font 54 | self.textColor = titleColor 55 | self.numberOfLines = numberOfLines 56 | self.adjustsFontSizeToFitWidth = true 57 | self.translatesAutoresizingMaskIntoConstraints = false 58 | } 59 | } 60 | 61 | /// Defines methods for creating view. 62 | protocol ViewSetable { 63 | 64 | /// Creates view hierarchy. 65 | func setupViews() 66 | 67 | /// Creates anchors between views. 68 | func setupConstraints() 69 | } 70 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/BaseViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 28/09/21. 6 | // 7 | 8 | import UIKit 9 | 10 | class BaseViewController: UIViewController { 11 | var collectionView: UICollectionView! 12 | var tabDelegate: TabBarViewControllerDelegate? 13 | 14 | let errorTextLabel: UILabel = { 15 | let label = UILabel() 16 | label.translatesAutoresizingMaskIntoConstraints = false 17 | label.numberOfLines = 0 18 | label.text = "" 19 | label.isHidden = true 20 | label.textColor = ColorLayout.default_grey 21 | label.font = UIFont(name: "HelveticaNeue-Semibold", size: 18.0) 22 | label.textAlignment = .center 23 | return label 24 | }() 25 | 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() 29 | layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 30 | layout.minimumLineSpacing = 0 31 | layout.minimumInteritemSpacing = 0 32 | collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout) 33 | self.view.addSubview(collectionView) 34 | collectionView.translatesAutoresizingMaskIntoConstraints = false 35 | collectionView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true 36 | collectionView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = true 37 | collectionView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0).isActive = true 38 | collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true 39 | collectionView.backgroundColor = .clear 40 | self.view.backgroundColor = ColorLayout.default_background 41 | self.view.addSubview(self.errorTextLabel) 42 | errorTextLabel.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 20).isActive = true 43 | errorTextLabel.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -20).isActive = true 44 | errorTextLabel.centerYAnchor.constraint(equalTo: self.collectionView.centerYAnchor).isActive = true 45 | } 46 | 47 | func viewDidSet(){ 48 | 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/FeedsResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeedsResponse.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 10/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - FeedsResponse 12 | struct FeedsResponse: Codable { 13 | let hotGifs: [HorizontalGIF] 14 | let hotCreators: [Creator] 15 | let hotImages: [HorizontalGIF] 16 | let newCreators: [Creator] 17 | let verifiedGifs, soundGifs, verifiedImages, verticalGifs: [HorizontalGIF] 18 | let longGifs, horizontalGifs: [HorizontalGIF] 19 | } 20 | 21 | // MARK: - HorizontalGIF 22 | struct HorizontalGIF: Codable { 23 | let id: String? 24 | let createDate: Int? 25 | let hasAudio: Bool? 26 | let width, height, likes: Int? 27 | let tags: [String]? 28 | let verified: Bool? 29 | let views, duration: Int? 30 | let published: Bool? 31 | let urls: Urls? 32 | let userName: String? 33 | let type: Int? 34 | let avgColor: String? 35 | let gallery: String? 36 | let user: User? 37 | } 38 | 39 | // MARK: - Urls 40 | struct Urls: Codable { 41 | let sd, hd: String? 42 | let gif: String? 43 | let poster: String? 44 | let thumbnail: String? 45 | let vthumbnail: String? 46 | } 47 | 48 | // MARK: - User 49 | struct User: Codable { 50 | let creationtime, followers, following, gifs: Int? 51 | let name: String? 52 | let profileImageURL: String? 53 | let profileURL: String? 54 | let publishedGifs, subscription: Int? 55 | let url: String? 56 | let username: String? 57 | let verified: Bool? 58 | let views: Int? 59 | 60 | enum CodingKeys: String, CodingKey { 61 | case creationtime, followers, following, gifs, name 62 | case profileImageURL = "profileImageUrl" 63 | case profileURL = "profileUrl" 64 | case publishedGifs, subscription, url, username, verified, views 65 | } 66 | } 67 | 68 | // MARK: - Creator 69 | struct Creator: Codable { 70 | let id, name: String? 71 | let followers, gifs: Int? 72 | let verified: Bool? 73 | let views: Int? 74 | let thumbnail: String? 75 | let poster: String? 76 | let preview: String? 77 | let avatarURL: String? 78 | 79 | enum CodingKeys: String, CodingKey { 80 | case id, name, followers, gifs, verified, views, thumbnail, poster, preview 81 | case avatarURL = "avatarUrl" 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/IconTextView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IconTextView.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 10/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | class IconTextView: UIView { 13 | 14 | private var iconImage: UIImage? 15 | private var text: String? 16 | 17 | let imageView: UIImageView = { 18 | let view = UIImageView() 19 | view.translatesAutoresizingMaskIntoConstraints = false 20 | return view 21 | }() 22 | 23 | let textLabel: UILabel = { 24 | let view = UILabel() 25 | view.textColor = .white 26 | view.translatesAutoresizingMaskIntoConstraints = false 27 | view.font = UIFont(name: "HelveticaNeue-Semibold", size: 14.0) 28 | view.textAlignment = .center 29 | return view 30 | }() 31 | 32 | init(frame: CGRect, icon: UIImage, text: String){ 33 | super.init(frame: frame) 34 | self.iconImage = icon 35 | self.text = text 36 | self.setupView() 37 | } 38 | 39 | override init(frame: CGRect) { 40 | super.init(frame: frame) 41 | self.setupView() 42 | } 43 | 44 | required init(coder aDecoder: NSCoder) { 45 | fatalError("init(coder:) has not been implemented") 46 | } 47 | 48 | func setupView(){ 49 | self.addSubview(imageView) 50 | 51 | imageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true 52 | imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true 53 | imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true 54 | imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: 1).isActive = true 55 | imageView.image = self.iconImage 56 | imageView.tintColor = .white 57 | imageView.alpha = 0.8 58 | 59 | 60 | self.addSubview(textLabel) 61 | textLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 4).isActive = true 62 | textLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true 63 | textLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true 64 | textLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true 65 | textLabel.text = self.text 66 | textLabel.alpha = 0.8 67 | textLabel.adjustsFontSizeToFitWidth = true 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 9 | *.xcscmblueprint 10 | *.xccheckout 11 | 12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 13 | build/ 14 | DerivedData/ 15 | *.moved-aside 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | 28 | ## App packaging 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | # Package.pins 42 | # Package.resolved 43 | # *.xcodeproj 44 | # 45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 46 | # hence it is not needed unless you have added a package configuration file to your project 47 | # .swiftpm 48 | 49 | .build/ 50 | 51 | # CocoaPods 52 | # 53 | # We recommend against adding the Pods directory to your .gitignore. However 54 | # you should judge for yourself, the pros and cons are mentioned at: 55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 56 | # 57 | Pods/ 58 | # 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | *.xcworkspace 61 | 62 | # Carthage 63 | # 64 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 65 | # Carthage/Checkouts 66 | 67 | Carthage/Build/ 68 | 69 | # Accio dependency management 70 | Dependencies/ 71 | .accio/ 72 | 73 | # fastlane 74 | # 75 | # It is recommended to not store the screenshots in the git repo. 76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 77 | # For more information about the recommended setup visit: 78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 79 | 80 | fastlane/report.xml 81 | fastlane/Preview.html 82 | fastlane/screenshots/**/*.png 83 | fastlane/test_output 84 | 85 | # Code Injection 86 | # 87 | # After new code Injection tools there's a generated folder /iOSInjectionProject 88 | # https://github.com/johnno1962/injectionforxcode 89 | 90 | iOSInjectionProject/ 91 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/TikPornResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TikPornResponse.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 15/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | // This file was generated from JSON Schema using quicktype, do not modify it directly. 10 | // To parse the JSON, add this file to your project and do: 11 | // 12 | // let tikPornResponse = try? newJSONDecoder().decode(TikPornResponse.self, from: jsonData) 13 | 14 | import Foundation 15 | 16 | // MARK: - TikPornResponse 17 | struct TikPornResponse: Codable { 18 | let code: Int? 19 | let message: String? 20 | let data: [TikPornPost]? 21 | } 22 | 23 | // MARK: - Datum 24 | struct TikPornPost: Codable { 25 | let videoID, ewokVideoID, actionID: Int? 26 | let actionName: String? 27 | let startPosition, encodingTypeID: Int? 28 | let datumExtension: String? 29 | let mainCategory, producerID: Int? 30 | let tagVideoID: String? 31 | let onCDN, status: Int? 32 | let producerName: String? 33 | let producerAvatar: Int? 34 | let pornstars: [TikPornstar]? 35 | let userRating: Int? 36 | let likeCount: String? 37 | let tags: [TikTag]? 38 | let filename: String? 39 | let fileurl: String? 40 | let mimetype: String? 41 | let userID: Int? 42 | 43 | enum CodingKeys: String, CodingKey { 44 | case videoID = "video_id" 45 | case ewokVideoID = "ewok_video_id" 46 | case actionID = "action_id" 47 | case actionName = "action_name" 48 | case startPosition = "start_position" 49 | case encodingTypeID = "encoding_type_id" 50 | case datumExtension = "extension" 51 | case mainCategory = "main_category" 52 | case producerID = "producer_id" 53 | case tagVideoID = "tag_video_id" 54 | case onCDN = "on_cdn" 55 | case status 56 | case producerName = "producer_name" 57 | case producerAvatar = "producer_avatar" 58 | case pornstars 59 | case userRating = "user_rating" 60 | case likeCount = "like_count" 61 | case tags, filename, fileurl, mimetype 62 | case userID = "user_id" 63 | } 64 | } 65 | 66 | // MARK: - Pornstar 67 | struct TikPornstar: Codable { 68 | let id, name, slug: String? 69 | let avatarImg: Int? 70 | 71 | enum CodingKeys: String, CodingKey { 72 | case id, name, slug 73 | case avatarImg = "avatar_img" 74 | } 75 | } 76 | 77 | // MARK: - Tag 78 | struct TikTag: Codable { 79 | let id, name: String? 80 | } 81 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Home/HomeViewCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeViewCoordinator.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class HomeViewCoordinator { 12 | 13 | private var currentPage: Int = 1 14 | 15 | public var videos: [Video] = [] 16 | 17 | public var searchText: String? = nil 18 | public var category: String? = nil 19 | 20 | private var delegate: HomeViewDelegate! 21 | 22 | init(_ delegate: HomeViewDelegate) { 23 | self.delegate = delegate 24 | } 25 | 26 | func loadData(){ 27 | APIService.shared.sendSearchRequest(searchText: self.searchText, category: self.category ?? "teen-18-1", page: currentPage) { result in 28 | switch result { 29 | case .success(let videos): 30 | self.videos.append(contentsOf: videos.videos) 31 | self.delegate.reloadView() 32 | case .failure(let error): 33 | if let errorRes = error as? APIServiceError { 34 | switch errorRes { 35 | case .unknown: 36 | self.delegate.showError(message: "Unknown error") 37 | case .decodeError(let error): 38 | self.delegate.showError(message: error.localizedDescription) 39 | case .noDataFound: 40 | self.delegate.showError(message: "No data found") 41 | case .error(let errorResponse): 42 | if errorResponse.code == "2001" && self.videos.count <= 0 { 43 | self.delegate.showError(message: errorResponse.message) 44 | } 45 | } 46 | 47 | } 48 | else if self.videos.count <= 0 { 49 | self.delegate.showError(message: error.localizedDescription) 50 | } 51 | print(error) 52 | } 53 | } 54 | } 55 | 56 | func search(searchText: String?){ 57 | self.searchText = searchText 58 | self.category = nil 59 | self.currentPage = 1 60 | self.loadData() 61 | } 62 | 63 | func searchForCategory(category : String){ 64 | self.currentPage = 1 65 | self.searchText = nil 66 | self.category = category 67 | self.loadData() 68 | } 69 | 70 | func fetchNext(){ 71 | currentPage += 1 72 | self.loadData() 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/StarView/StarViewCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StarViewCoordinator.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 04/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class StarViewCoordinator { 12 | 13 | private var delegate: StarViewControllerDelegate! 14 | 15 | public var star: Star! 16 | public var images: [String] = [] 17 | 18 | private var videoPage: Int = 1 19 | private var imagesPage: Int = 1 20 | 21 | init(_ delegate: StarViewControllerDelegate) { 22 | self.delegate = delegate 23 | self.star = delegate.getStar() 24 | } 25 | 26 | 27 | func loadVideos(){ 28 | APIService.shared.getStarVideos(starName: self.star.starName!, page: self.videoPage, completionHandler: { result in 29 | switch result { 30 | case .success(let videos): 31 | if self.star.starVideos == nil { 32 | self.star.starVideos = [] 33 | } 34 | self.star.starVideos?.append(contentsOf: videos) 35 | DispatchQueue.main.async { 36 | if self.star.starVideos?.count == 0 { 37 | self.delegate.reloadView("No videos found for pornstar " + (self.star.starName ?? "") + " :(") 38 | } 39 | else{ 40 | self.delegate.reloadView(nil) 41 | } 42 | } 43 | case .failure(let error): 44 | self.delegate.videosCompleted = true 45 | DispatchQueue.main.async { 46 | self.delegate.reloadView(nil) 47 | } 48 | print(error) 49 | } 50 | }) 51 | } 52 | 53 | func loadImages(){ 54 | APIService.shared.getStarImages(offSet: self.imagesPage, starName: self.star.starName!) { response in 55 | switch response { 56 | case .success(let res): 57 | self.images.append(contentsOf: res.map({ $0.tURL460 ?? "" })) 58 | self.delegate.reloadImages(res.count == 0 ? "No images found for \(self.star.starName!) pornstar :(" : nil) 59 | case .failure(let error): 60 | print(error) 61 | self.delegate.reloadImages(error.localizedDescription) 62 | } 63 | } 64 | } 65 | 66 | func fetchNextVideos(){ 67 | self.videoPage += 1 68 | self.loadVideos() 69 | } 70 | 71 | func fetchNextImages() { 72 | self.imagesPage += 1 73 | self.loadImages() 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /ICO-Visualizer/Extensions/String+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Extensions.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 09/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension String { 13 | func capitalizingFirstLetter() -> String { 14 | return prefix(1).uppercased() + self.lowercased().dropFirst() 15 | } 16 | 17 | mutating func capitalizeFirstLetter() { 18 | self = self.capitalizingFirstLetter() 19 | } 20 | 21 | func toDate() -> Date? { 22 | let dateFormatterPrint = DateFormatter() 23 | dateFormatterPrint.dateFormat = "yyyy-MM-dd HH:mm:ss" 24 | return dateFormatterPrint.date(from: self) 25 | } 26 | 27 | func capturedGroups(withRegex pattern: String) -> [String] { 28 | var results = [String]() 29 | 30 | var regex: NSRegularExpression 31 | do { 32 | regex = try NSRegularExpression(pattern: pattern, options: []) 33 | } catch { 34 | return results 35 | } 36 | 37 | let matches = regex.matches(in: self, options: [], range: NSRange(location:0, length: self.count)) 38 | 39 | for item in matches { 40 | let lastRangeIndex = item.numberOfRanges - 1 41 | guard lastRangeIndex >= 1 else { return results } 42 | 43 | for i in 0...lastRangeIndex { 44 | let capturedGroupIndex = item.range(at: i) 45 | if(capturedGroupIndex.length>0) 46 | { 47 | let matchedString = (self as NSString).substring(with: capturedGroupIndex) 48 | results.append(matchedString) 49 | } 50 | } 51 | } 52 | 53 | 54 | return results 55 | } 56 | 57 | func getQueryStringParameter(param: String) -> String? { 58 | guard let url = URLComponents(string: self) else { return nil } 59 | return url.queryItems?.first(where: { $0.name == param })?.value 60 | } 61 | 62 | func hexStringToUIColor () -> UIColor { 63 | var cString:String = self.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() 64 | 65 | if (cString.hasPrefix("#")) { 66 | cString.remove(at: cString.startIndex) 67 | } 68 | 69 | if ((cString.count) != 6) { 70 | return UIColor.gray 71 | } 72 | 73 | var rgbValue:UInt64 = 0 74 | Scanner(string: cString).scanHexInt64(&rgbValue) 75 | 76 | return UIColor( 77 | red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, 78 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, 79 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0, 80 | alpha: CGFloat(1.0) 81 | ) 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /ICO-Visualizer/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 24/09/2020. 6 | // Copyright © 2020 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | (UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController as? TabBarViewController)?.playReelsIfNeeded() 34 | } 35 | 36 | func sceneWillResignActive(_ scene: UIScene) { 37 | // Called when the scene will move from an active state to an inactive state. 38 | // This may occur due to temporary interruptions (ex. an incoming phone call). 39 | (UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.rootViewController as? TabBarViewController)?.pauseReelsIfNeeded() 40 | } 41 | 42 | func sceneWillEnterForeground(_ scene: UIScene) { 43 | // Called as the scene transitions from the background to the foreground. 44 | // Use this method to undo the changes made on entering the background. 45 | } 46 | 47 | func sceneDidEnterBackground(_ scene: UIScene) { 48 | // Called as the scene transitions from the foreground to the background. 49 | // Use this method to save data, release shared resources, and store enough scene-specific state information 50 | // to restore the scene back to its current state. 51 | } 52 | 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /ICO-Visualizer/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 24/09/2020. 6 | // Copyright © 2020 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import AVFoundation 11 | import AlamofireNetworkActivityLogger 12 | 13 | @UIApplicationMain 14 | class AppDelegate: UIResponder, UIApplicationDelegate { 15 | 16 | private var audioLevel : Float = 0.0 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 19 | do { 20 | try AVAudioSession.sharedInstance().setCategory(.playback) 21 | try AVAudioSession.sharedInstance().setActive(true, options: []) 22 | AVAudioSession.sharedInstance().addObserver(self, forKeyPath: "outputVolume", options: NSKeyValueObservingOptions.new, context: nil) 23 | audioLevel = AVAudioSession.sharedInstance().outputVolume 24 | } catch { 25 | print(error) 26 | } 27 | #if DEBUG 28 | NetworkActivityLogger.shared.level = .debug 29 | NetworkActivityLogger.shared.startLogging() 30 | #endif 31 | return true 32 | } 33 | 34 | override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 35 | if keyPath == "outputVolume"{ 36 | let audioSession = AVAudioSession.sharedInstance() 37 | if audioSession.outputVolume > audioLevel { 38 | NotificationCenter.default.post(Notification(name: .didPressVolumeUp, object: nil, userInfo: ["volume" : audioSession.outputVolume])) 39 | } 40 | if audioSession.outputVolume < audioLevel { 41 | NotificationCenter.default.post(Notification(name: .didPressVolumeDown, object: nil, userInfo: ["volume" : audioSession.outputVolume])) 42 | } 43 | audioLevel = audioSession.outputVolume 44 | } 45 | } 46 | 47 | // MARK: UISceneSession Lifecycle 48 | 49 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 50 | // Called when a new scene session is being created. 51 | // Use this method to select a configuration to create the new scene with. 52 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 53 | } 54 | 55 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 56 | // Called when the user discards a scene session. 57 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 58 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/LeftImageCaption/LeftImageCaptionTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PokemonListTableViewCell.swift 3 | // pokemon-visualizer 4 | // 5 | // Created by Anonymous on 26/10/21. 6 | // 7 | 8 | import UIKit 9 | import SDWebImage 10 | 11 | class LeftImageCaptionTableViewCell : FullWidthCollectionViewCell { 12 | 13 | let background: UIView = { 14 | let bView = UIView() 15 | bView.translatesAutoresizingMaskIntoConstraints = false 16 | bView.backgroundColor = ColorLayout.default_tab_background 17 | bView.setShadowAndCorner(cornerRadius: 8) 18 | return bView 19 | }() 20 | 21 | let avatarView: UIImageView = { 22 | let iView = UIImageView() 23 | iView.translatesAutoresizingMaskIntoConstraints = false 24 | return iView 25 | }() 26 | 27 | let nameLabel: UILabel = { 28 | let label = UILabel() 29 | label.translatesAutoresizingMaskIntoConstraints = false 30 | //label.font = FontLayout.medium16 31 | return label 32 | }() 33 | 34 | override init(frame: CGRect) { 35 | super.init(frame: frame) 36 | self.setupView() 37 | } 38 | 39 | required init?(coder: NSCoder) { 40 | fatalError("init(coder:) has not been implemented") 41 | } 42 | 43 | func setup(imageUrl: String?, caption: String?){ 44 | self.nameLabel.text = caption 45 | self.avatarView.sd_setImage(with: URL(string: imageUrl ?? ""), completed: nil) 46 | } 47 | 48 | private func setupView(){ 49 | self.contentView.addSubview(background) 50 | self.backgroundColor = .clear 51 | self.contentView.backgroundColor = .clear 52 | self.background.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 15).isActive = true 53 | self.background.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -15).isActive = true 54 | self.background.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 30).isActive = true 55 | self.background.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -30).isActive = true 56 | 57 | self.background.addSubview(self.avatarView) 58 | self.avatarView.heightAnchor.constraint(equalToConstant: 60).isActive = true 59 | self.avatarView.widthAnchor.constraint(equalToConstant: 60).isActive = true 60 | self.avatarView.topAnchor.constraint(equalTo: self.background.topAnchor, constant: 8).isActive = true 61 | self.avatarView.leadingAnchor.constraint(equalTo: self.background.leadingAnchor, constant: 8).isActive = true 62 | self.avatarView.bottomAnchor.constraint(equalTo: self.background.bottomAnchor, constant: -8).isActive = true 63 | 64 | self.background.addSubview(self.nameLabel) 65 | 66 | self.nameLabel.leadingAnchor.constraint(equalTo: self.avatarView.trailingAnchor, constant: 8).isActive = true 67 | self.nameLabel.topAnchor.constraint(equalTo: self.avatarView.topAnchor).isActive = true 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/VideosResponseModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoResponseModel.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - VideoResponse 12 | struct VideosResponseModel: Codable { 13 | let videos: [Video] 14 | } 15 | 16 | // MARK: - VideoResult 17 | struct VideoResult: Codable { 18 | let video: Video 19 | } 20 | 21 | // MARK: - Video 22 | struct Video: Codable { 23 | let duration: String? 24 | let views: Int? 25 | let videoID: String? 26 | let ratings: Int? 27 | let rating: Rating? 28 | let title: String? 29 | let url: String? 30 | let defaultThumb, thumb: String? 31 | let publishDate: String? 32 | let thumbs: [Thumb]? 33 | let tags: [Tag]? 34 | let pornstars: [Pornstar]? 35 | let categories: [Category]? 36 | let segment: Segment? 37 | 38 | enum CodingKeys: String, CodingKey { 39 | case duration, views 40 | case videoID = "video_id" 41 | case ratings, title, url 42 | case defaultThumb = "default_thumb" 43 | case thumb 44 | case rating 45 | case publishDate = "publish_date" 46 | case thumbs, tags, pornstars, categories, segment 47 | } 48 | } 49 | 50 | struct Rating: Codable { 51 | let rating: Double 52 | let ratingString: String 53 | 54 | // Where we determine what type the value is 55 | init(from decoder: Decoder) throws { 56 | let container = try decoder.singleValueContainer() 57 | 58 | // Check for a boolean 59 | do { 60 | rating = try container.decode(Double.self) 61 | ratingString = "0" 62 | } catch { 63 | // Check for an integer 64 | ratingString = try container.decode(String.self) 65 | rating = 0 66 | } 67 | } 68 | 69 | // We need to go back to a dynamic type, so based on the data we have stored, encode to the proper type 70 | func encode(to encoder: Encoder) throws { 71 | var container = encoder.singleValueContainer() 72 | try rating == 0 ? container.encode(ratingString) : container.encode(0) 73 | } 74 | } 75 | 76 | // MARK: - Category 77 | struct Category: Codable { 78 | let category: String? 79 | let id: String? 80 | } 81 | 82 | // MARK: - Pornstar 83 | struct Pornstar: Codable { 84 | let pornstarName: String? 85 | 86 | enum CodingKeys: String, CodingKey { 87 | case pornstarName = "pornstar_name" 88 | } 89 | } 90 | 91 | enum Segment: String, Codable { 92 | case gay = "gay" 93 | case straight = "straight" 94 | } 95 | 96 | // MARK: - Tag 97 | struct Tag: Codable { 98 | let tagName: String? 99 | 100 | enum CodingKeys: String, CodingKey { 101 | case tagName = "tag_name" 102 | } 103 | } 104 | 105 | // MARK: - Thumb 106 | struct Thumb: Codable { 107 | let size: String? 108 | let width, height: String? 109 | let src: String? 110 | } 111 | -------------------------------------------------------------------------------- /ICO-Visualizer/Models/TikResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TikResponse.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 11/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - TikResponse 12 | struct TikResponse: Codable { 13 | let data: DataClass? 14 | let meta: Meta? 15 | } 16 | 17 | // MARK: - DataClass 18 | struct DataClass: Codable { 19 | let posts: [Post]? 20 | } 21 | 22 | // MARK: - Post 23 | struct Post: Codable { 24 | let id: Int? 25 | let uuid: String? 26 | let authorID: Int? 27 | let postDescription, vimeoID, vimeoURI, vimeoThumbnailURL: String? 28 | let viemoGIFURL: String? 29 | let redgifs: Bool? 30 | let redGifsThumbnailURL: String? 31 | let redGifsVideoURL: String? 32 | let status: Status? 33 | let width, height: Int? 34 | let mediaID, thumbnailID, thumbnailName, videoName: String? 35 | let postCount: Int? 36 | let source: String? 37 | let visible: Bool? 38 | let reactionInitial: Int? 39 | let createdAt, updatedAt: String? 40 | let author: Author? 41 | let tags: [TikPornTag]? 42 | let count: Count? 43 | let index: Int? 44 | 45 | enum CodingKeys: String, CodingKey { 46 | case id, uuid 47 | case authorID = "authorId" 48 | case postDescription = "description" 49 | case vimeoID = "vimeoId" 50 | case vimeoURI = "vimeoUri" 51 | case vimeoThumbnailURL = "vimeoThumbnailUrl" 52 | case viemoGIFURL = "viemoGifUrl" 53 | case redgifs 54 | case redGifsThumbnailURL = "redGifsThumbnailUrl" 55 | case redGifsVideoURL = "redGifsVideoUrl" 56 | case status, width, height 57 | case mediaID = "mediaId" 58 | case thumbnailID = "thumbnailId" 59 | case thumbnailName, videoName 60 | case postCount = "count" 61 | case source, visible, reactionInitial, createdAt, updatedAt, author, tags 62 | case count = "_count" 63 | case index 64 | } 65 | } 66 | 67 | // MARK: - Author 68 | struct Author: Codable { 69 | let id: Int? 70 | let uuid, email: String? 71 | let emailVerified, publisher: Bool? 72 | let name: String? 73 | let authorDescription: Description? 74 | let website, avatarName, avatarID: String? 75 | let createdAt: String? 76 | 77 | enum CodingKeys: String, CodingKey { 78 | case id, uuid, email, emailVerified, publisher, name 79 | case authorDescription = "description" 80 | case website, avatarName 81 | case avatarID = "avatarId" 82 | case createdAt 83 | } 84 | } 85 | 86 | enum Description: String, Codable { 87 | case officialXxxtikPage = "Official xxxtik page." 88 | } 89 | 90 | // MARK: - Count 91 | struct Count: Codable { 92 | let reactions: Int? 93 | } 94 | 95 | enum Status: String, Codable { 96 | case approved = "approved" 97 | } 98 | 99 | // MARK: - Tag 100 | struct TikPornTag: Codable { 101 | let id: Int? 102 | let uuid, name: String? 103 | } 104 | 105 | // MARK: - Meta 106 | struct Meta: Codable { 107 | let key: String? 108 | } 109 | 110 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/WebView/WebViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import WebKit 11 | 12 | class WebViewController: UIViewController { 13 | let webView: WKWebView = { 14 | let webView = WKWebView() 15 | webView.translatesAutoresizingMaskIntoConstraints = false 16 | webView.backgroundColor = .clear 17 | return webView 18 | }() 19 | 20 | let closeButton: UIButton = { 21 | let button = UIButton() 22 | button.setTitle("", for: .normal) 23 | button.translatesAutoresizingMaskIntoConstraints = false 24 | button.setImage(UIImage(named: "back_icon"), for: .normal) 25 | button.tintColor = ColorLayout.default_orange 26 | return button 27 | }() 28 | 29 | let titleLabel: UILabel = { 30 | let label = UILabel() 31 | label.translatesAutoresizingMaskIntoConstraints = false 32 | label.font = UIFont(name: "HelveticaNeue-Bold", size: 20) 33 | label.textAlignment = .center 34 | label.numberOfLines = 1 35 | label.textColor = ColorLayout.default_text 36 | return label 37 | }() 38 | 39 | public var url: String! 40 | public var titleText: String? 41 | 42 | override func viewDidLoad() { 43 | super.viewDidLoad() 44 | self.view.backgroundColor = ColorLayout.default_background 45 | 46 | self.view.addSubview(closeButton) 47 | closeButton.heightAnchor.constraint(equalToConstant: 24).isActive = true 48 | closeButton.widthAnchor.constraint(equalToConstant: 24).isActive = true 49 | closeButton.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 16).isActive = true 50 | closeButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16).isActive = true 51 | closeButton.addTarget(self, action: #selector(onCloseTap(_:)), for: .touchUpInside) 52 | 53 | self.view.addSubview(titleLabel) 54 | titleLabel.leadingAnchor.constraint(equalTo: self.closeButton.trailingAnchor, constant: 12).isActive = true 55 | titleLabel.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -24).isActive = true 56 | titleLabel.centerYAnchor.constraint(equalTo: self.closeButton.centerYAnchor).isActive = true 57 | 58 | self.view.addSubview(webView) 59 | webView.topAnchor.constraint(equalTo: self.closeButton.bottomAnchor, constant: 14).isActive = true 60 | webView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true 61 | webView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true 62 | webView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true 63 | 64 | let url = URL(string: url)! 65 | webView.load(URLRequest(url: url)) 66 | self.titleLabel.text = self.titleText 67 | } 68 | 69 | @objc func onCloseTap(_ button: UIButton) { 70 | //self.navigationController?.popViewController(animated: true) 71 | self.dismiss(animated: true, completion: nil) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/IconSelectionView/IconSelectionViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IconSelectionViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 05/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class IconSelectionViewController: BaseViewController { 12 | 13 | private var icons: [String] = ["AlternateAppIconDuet", "AlternateAppIconSphere", "AlternateAppIconArmony"] 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | collectionView.setupView(self) 18 | 19 | if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { 20 | flowLayout.headerReferenceSize = CGSize(width: UIScreen.main.bounds.width, height: 45) 21 | flowLayout.sectionInset = UIEdgeInsets(top: 12, left: 0, bottom: 0, right: 12) 22 | flowLayout.sectionHeadersPinToVisibleBounds = true 23 | flowLayout.estimatedItemSize = CGSize( 24 | width: UIScreen.main.bounds.width - 2, 25 | height: 200 26 | ) 27 | flowLayout.invalidateLayout() 28 | } 29 | 30 | collectionView.reloadData() 31 | } 32 | } 33 | 34 | extension IconSelectionViewController: UICollectionViewDelegate, UICollectionViewDataSource { 35 | 36 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 37 | switch kind { 38 | case UICollectionView.elementKindSectionHeader: 39 | 40 | let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TitleSectionHeaderReusableView.className, for: indexPath) as! TitleSectionHeaderReusableView 41 | headerView.setupTitle(title: "Select Icon") 42 | 43 | return headerView 44 | 45 | case UICollectionView.elementKindSectionFooter: 46 | return UICollectionReusableView() 47 | 48 | default: 49 | assert(false, "Unexpected element kind") 50 | } 51 | } 52 | 53 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 54 | return 4 55 | } 56 | 57 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 58 | let selectIconCell = collectionView.dequeueReusableCell(withReuseIdentifier: NavigationButtonCollectionViewCell.className, for: indexPath) as! NavigationButtonCollectionViewCell 59 | if indexPath.row == 0 { 60 | selectIconCell.setup(title: "Default Icon") { 61 | UIApplication.shared.setAlternateIconName(nil) { (error) in } 62 | self.navigationController?.popViewController(animated: true) 63 | } 64 | } 65 | else{ 66 | selectIconCell.setup(title: self.icons[indexPath.row - 1]) { 67 | UIApplication.shared.setAlternateIconName(self.icons[indexPath.row - 1]) { (error) in } 68 | self.navigationController?.popViewController(animated: true) 69 | } 70 | } 71 | 72 | return selectIconCell 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/ImageCell/ImageCollectionViewCell.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 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ICO-Visualizer/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | {"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/FakeView/FakeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FakeViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 07/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FakeViewController: UIViewController { 12 | 13 | let collectionView: UICollectionView = { 14 | let flowLayout = UICollectionViewFlowLayout() 15 | flowLayout.estimatedItemSize = CGSize( 16 | width: UIScreen.main.bounds.width - 2, 17 | height: 200 18 | ) 19 | let cView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) 20 | cView.translatesAutoresizingMaskIntoConstraints = false 21 | 22 | cView.register(LeftImageCaptionTableViewCell.self, forCellWithReuseIdentifier: LeftImageCaptionTableViewCell.className) 23 | return cView 24 | }() 25 | 26 | let titleLabel: UILabel = { 27 | let label = UILabel() 28 | label.translatesAutoresizingMaskIntoConstraints = false 29 | label.font = UIFont(name: "HelveticaNeue-Bold", size: 24) 30 | label.textAlignment = .left 31 | label.numberOfLines = 1 32 | label.text = "Pokemons" 33 | label.textColor = ColorLayout.default_text 34 | return label 35 | }() 36 | 37 | private var pokemonList: [PokemonListResult] = [] 38 | 39 | override func viewDidLoad() { 40 | super.viewDidLoad() 41 | 42 | self.view.addSubview(titleLabel) 43 | titleLabel.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor, constant: 24).isActive = true 44 | titleLabel.leadingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.leadingAnchor).isActive = true 45 | titleLabel.trailingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.trailingAnchor).isActive = true 46 | 47 | self.view.addSubview(collectionView) 48 | collectionView.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor, constant: 12).isActive = true 49 | collectionView.leadingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.leadingAnchor).isActive = true 50 | collectionView.trailingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.trailingAnchor).isActive = true 51 | collectionView.bottomAnchor.constraint(equalTo: self.view.layoutMarginsGuide.bottomAnchor).isActive = true 52 | collectionView.delegate = self 53 | collectionView.dataSource = self 54 | 55 | APIService.shared.fetchPokemons { response in 56 | switch response { 57 | case .success(let list): 58 | self.pokemonList = list.results 59 | DispatchQueue.main.async { 60 | self.collectionView.reloadData() 61 | } 62 | case .failure(let error): 63 | print(error) 64 | } 65 | } 66 | } 67 | } 68 | 69 | extension FakeViewController: UICollectionViewDelegate, UICollectionViewDataSource { 70 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 71 | return self.pokemonList.count 72 | } 73 | 74 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 75 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: LeftImageCaptionTableViewCell.className, for: indexPath) as! LeftImageCaptionTableViewCell 76 | cell.setup(imageUrl: self.pokemonList[indexPath.row].imageUrl, caption: self.pokemonList[indexPath.row].name) 77 | return cell 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/ReelSourceSelection/ReelSourceSelectionViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReelSourceSelectionViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 16/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ReelSourceSelectionViewController: BaseViewController { 12 | 13 | private let sources: [APIService.ReelSource] = [.redgifs, .xxxtik, .tikporn] 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | collectionView.setupView(self) 18 | 19 | if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { 20 | flowLayout.headerReferenceSize = CGSize(width: UIScreen.main.bounds.width, height: 45) 21 | flowLayout.sectionInset = UIEdgeInsets(top: 12, left: 0, bottom: 0, right: 12) 22 | flowLayout.sectionHeadersPinToVisibleBounds = true 23 | flowLayout.estimatedItemSize = CGSize( 24 | width: UIScreen.main.bounds.width - 2, 25 | height: 200 26 | ) 27 | flowLayout.invalidateLayout() 28 | } 29 | 30 | collectionView.reloadData() 31 | } 32 | } 33 | 34 | extension ReelSourceSelectionViewController: UICollectionViewDelegate, UICollectionViewDataSource { 35 | 36 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 37 | switch kind { 38 | case UICollectionView.elementKindSectionHeader: 39 | 40 | let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TitleSectionHeaderReusableView.className, for: indexPath) as! TitleSectionHeaderReusableView 41 | headerView.setupTitle(title: "Select Reel Data Source") 42 | 43 | return headerView 44 | 45 | case UICollectionView.elementKindSectionFooter: 46 | return UICollectionReusableView() 47 | 48 | default: 49 | assert(false, "Unexpected element kind") 50 | } 51 | } 52 | 53 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 54 | return sources.count 55 | } 56 | 57 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 58 | let selectIconCell = collectionView.dequeueReusableCell(withReuseIdentifier: NavigationButtonCollectionViewCell.className, for: indexPath) as! NavigationButtonCollectionViewCell 59 | if indexPath.row == 0 { 60 | selectIconCell.setup(title: "Redgifs") { 61 | UserPreferences.shared.reelSource = self.sources[indexPath.row] 62 | NotificationCenter.default.post(name: .didChangeReelPreference, object: nil) 63 | self.navigationController?.popViewController(animated: true) 64 | } 65 | } 66 | else if indexPath.row == 1 { 67 | selectIconCell.setup(title: "XXX Tik") { 68 | UserPreferences.shared.reelSource = self.sources[indexPath.row] 69 | NotificationCenter.default.post(name: .didChangeReelPreference, object: nil) 70 | self.navigationController?.popViewController(animated: true) 71 | } 72 | } 73 | else if indexPath.row == 2 { 74 | selectIconCell.setup(title: "Tik Porn") { 75 | UserPreferences.shared.reelSource = self.sources[indexPath.row] 76 | NotificationCenter.default.post(name: .didChangeReelPreference, object: nil) 77 | self.navigationController?.popViewController(animated: true) 78 | } 79 | } 80 | return selectIconCell 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/TabBarView/TabBarViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabBarViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 21/09/21. 6 | // 7 | 8 | import UIKit 9 | 10 | class TabBarViewController: UIViewController { 11 | 12 | @IBOutlet var tabItems: Array? 13 | 14 | @IBOutlet weak var headerView: UIView! 15 | @IBOutlet weak var headerHeightConstraing: NSLayoutConstraint! 16 | private let defaultHeaderHeight: CGFloat = 70 17 | 18 | 19 | @IBOutlet weak var settingsButton: UIButton! 20 | 21 | @IBOutlet weak var headerLogoImageView: UIImageView! 22 | private var mainNavigationController: BaseNavigationController! 23 | 24 | lazy var controllers = [HomeViewController(), BookmarksViewController(), StarsViewController(), ReelsViewController()] 25 | 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | NotificationCenter.default.addObserver(self, selector: #selector(onDidEnterFakePin(_:)), name: .didEnterFakePin, object: nil) 29 | } 30 | 31 | @objc func onDidEnterFakePin(_ notification: Notification) 32 | { 33 | DispatchQueue.main.async { 34 | let vc = FakeViewController() 35 | vc.modalPresentationStyle = .fullScreen 36 | self.present(vc, animated: false, completion: nil) 37 | } 38 | } 39 | 40 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 41 | if let vc = segue.destination as? BaseNavigationController, 42 | segue.identifier == "mainSegue" { 43 | self.mainNavigationController = vc 44 | self.mainNavigationController.setNavigationBarHidden(true, animated: false) 45 | self.setViewController(index: 0) 46 | } 47 | } 48 | 49 | private func setViewController(index: Int){ 50 | self.headerHeightConstraing.constant = index == 3 ? 0 : self.defaultHeaderHeight + UIScreen.main.topSafeAreaHeight 51 | self.headerView.isHidden = index == 3 52 | let vc = controllers[index] 53 | vc.tabDelegate = self 54 | self.mainNavigationController.setViewControllers([vc], animated: false) 55 | 56 | for item in tabItems! { 57 | item.setTitle("", for: .normal) 58 | item.tintColor = ColorLayout.default_grey 59 | } 60 | self.tabItems![index].tintColor = ColorLayout.default_orange 61 | settingsButton.setTitle("", for: .normal) 62 | 63 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { 64 | vc.viewDidSet() 65 | } 66 | 67 | } 68 | @IBAction func onItemSelect(_ sender: UIButton) { 69 | self.setViewController(index: sender.tag) 70 | } 71 | 72 | @IBAction func onSettingsButtonTap(_ sender: UIButton) { 73 | if mainNavigationController.topViewController is SettingsViewController { 74 | return 75 | } 76 | let vc = SettingsViewController() 77 | self.mainNavigationController.pushViewController(vc, animated: true) 78 | } 79 | 80 | func pauseReelsIfNeeded(){ 81 | if let vc = mainNavigationController.topViewController as? ReelsViewController { 82 | vc.pauseVideoIfNeeded() 83 | } 84 | } 85 | 86 | func playReelsIfNeeded(){ 87 | if let vc = mainNavigationController.topViewController as? ReelsViewController { 88 | vc.playVideoIfNeeded() 89 | } 90 | } 91 | } 92 | 93 | extension TabBarViewController: TabBarViewControllerDelegate { 94 | func setPage(index: Int) { 95 | self.setViewController(index: index) 96 | } 97 | 98 | func searchForCategory(category: String) { 99 | if let vc = self.controllers[0] as? HomeViewController { 100 | vc.searchForCategory(category: category) 101 | } 102 | } 103 | 104 | func setHeader() { 105 | self.headerLogoImageView.image = UIImage(named: "header_logo") 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/SettingsView/SettingsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 05/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SettingsViewController: BaseViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | collectionView.setupView(self) 16 | 17 | if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { 18 | flowLayout.headerReferenceSize = CGSize(width: UIScreen.main.bounds.width, height: 45) 19 | flowLayout.sectionInset = UIEdgeInsets(top: 12, left: 0, bottom: 0, right: 12) 20 | flowLayout.sectionHeadersPinToVisibleBounds = true 21 | flowLayout.estimatedItemSize = CGSize( 22 | width: UIScreen.main.bounds.width - 2, 23 | height: 200 24 | ) 25 | flowLayout.invalidateLayout() 26 | } 27 | 28 | collectionView.reloadData() 29 | } 30 | } 31 | 32 | extension SettingsViewController: UICollectionViewDelegate, UICollectionViewDataSource { 33 | 34 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 35 | switch kind { 36 | case UICollectionView.elementKindSectionHeader: 37 | 38 | let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TitleSectionHeaderReusableView.className, for: indexPath) as! TitleSectionHeaderReusableView 39 | headerView.setupTitle(title: "Settings") 40 | 41 | return headerView 42 | 43 | case UICollectionView.elementKindSectionFooter: 44 | return UICollectionReusableView() 45 | 46 | default: 47 | assert(false, "Unexpected element kind") 48 | } 49 | } 50 | 51 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 52 | return 4 53 | } 54 | 55 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 56 | let faceIdToggle = collectionView.dequeueReusableCell(withReuseIdentifier: ToggleCollectionViewCell.className, for: indexPath) as! ToggleCollectionViewCell 57 | faceIdToggle.setup(title: "Face ID", isOn: UserPreferences.shared.faceIdEnabled) { isOn in 58 | UserPreferences.shared.faceIdEnabled = isOn 59 | } 60 | if indexPath.row == 1{ 61 | let iconSelectionCell = collectionView.dequeueReusableCell(withReuseIdentifier: NavigationButtonCollectionViewCell.className, for: indexPath) as! NavigationButtonCollectionViewCell 62 | iconSelectionCell.setup(title: "Select App Icon") { 63 | let iconSelectionVc = IconSelectionViewController() 64 | self.navigationController?.pushViewController(iconSelectionVc, animated: true) 65 | } 66 | return iconSelectionCell 67 | } 68 | if indexPath.row == 2{ 69 | let iconSelectionCell = collectionView.dequeueReusableCell(withReuseIdentifier: NavigationButtonCollectionViewCell.className, for: indexPath) as! NavigationButtonCollectionViewCell 70 | iconSelectionCell.setup(title: "Setup a fake PIN") { 71 | let pinVc = PinSetupViewController() 72 | pinVc.pinType = .fakePin 73 | self.navigationController?.pushViewController(pinVc, animated: true) 74 | } 75 | return iconSelectionCell 76 | } 77 | if indexPath.row == 3{ 78 | let iconSelectionCell = collectionView.dequeueReusableCell(withReuseIdentifier: NavigationButtonCollectionViewCell.className, for: indexPath) as! NavigationButtonCollectionViewCell 79 | iconSelectionCell.setup(title: "Select Reels source") { 80 | let pinVc = ReelSourceSelectionViewController() 81 | self.navigationController?.pushViewController(pinVc, animated: true) 82 | } 83 | return iconSelectionCell 84 | } 85 | return faceIdToggle 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /ICO-Visualizer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | ICO Visualizer 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIcons 12 | 13 | CFBundleAlternateIcons 14 | 15 | AlternateAppIconArmony 16 | 17 | CFBundleIconFiles 18 | 19 | AppIconArmony 20 | 21 | 22 | AlternateAppIconBase2 23 | 24 | CFBundleIconFiles 25 | 26 | AppIconBase2 27 | 28 | 29 | AlternateAppIconBase3 30 | 31 | CFBundleIconFiles 32 | 33 | AppIconBase3 34 | 35 | 36 | AlternateAppIconBase4 37 | 38 | CFBundleIconFiles 39 | 40 | AppIconBase4 41 | 42 | 43 | AlternateAppIconDevelop 44 | 45 | CFBundleIconFiles 46 | 47 | AppIconDevelop 48 | 49 | 50 | AlternateAppIconDevelopPremium 51 | 52 | CFBundleIconFiles 53 | 54 | AppIconDevelopPremium 55 | 56 | 57 | AlternateAppIconDuet 58 | 59 | CFBundleIconFiles 60 | 61 | AppIconDuet 62 | 63 | 64 | AlternateAppIconSphere 65 | 66 | CFBundleIconFiles 67 | 68 | AppIconSphere 69 | 70 | 71 | AlternateAppIconSport 72 | 73 | CFBundleIconFiles 74 | 75 | AppIconSport 76 | 77 | 78 | 79 | 80 | CFBundleIdentifier 81 | $(PRODUCT_BUNDLE_IDENTIFIER) 82 | CFBundleInfoDictionaryVersion 83 | 6.0 84 | CFBundleName 85 | $(PRODUCT_NAME) 86 | CFBundlePackageType 87 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 88 | CFBundleShortVersionString 89 | $(MARKETING_VERSION) 90 | CFBundleVersion 91 | $(CURRENT_PROJECT_VERSION) 92 | LSRequiresIPhoneOS 93 | 94 | NSFaceIDUsageDescription 95 | Unlock sensible content 96 | UIApplicationSceneManifest 97 | 98 | UIApplicationSupportsMultipleScenes 99 | 100 | UISceneConfigurations 101 | 102 | UIWindowSceneSessionRoleApplication 103 | 104 | 105 | UISceneConfigurationName 106 | Default Configuration 107 | UISceneDelegateClassName 108 | $(PRODUCT_MODULE_NAME).SceneDelegate 109 | UISceneStoryboardFile 110 | Main 111 | 112 | 113 | 114 | 115 | UILaunchStoryboardName 116 | LaunchScreen 117 | UIMainStoryboardFile 118 | Main 119 | UIRequiredDeviceCapabilities 120 | 121 | armv7 122 | 123 | UISupportedInterfaceOrientations 124 | 125 | UIInterfaceOrientationPortrait 126 | 127 | UISupportedInterfaceOrientations~ipad 128 | 129 | UIInterfaceOrientationPortrait 130 | UIInterfaceOrientationPortraitUpsideDown 131 | UIInterfaceOrientationLandscapeLeft 132 | UIInterfaceOrientationLandscapeRight 133 | 134 | UIUserInterfaceStyle 135 | Dark 136 | 137 | 138 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/StarCarouselCell/StarsCarouselCollectionViewCell.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 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/TitleCell/TitleCollectionViewCell.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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/BookmarksView/BookmarksViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BookmarksViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 05/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BookmarksViewController: BaseViewController { 12 | 13 | private var videoBookmarks: [Video] { 14 | return UserBookmakrs.shared.getVideosBookmarks().reversed() 15 | } 16 | 17 | private var starsBookmarks: [Star] { 18 | return UserBookmakrs.shared.getStarsBookmarks().reversed() 19 | } 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | collectionView.setupView(self) 24 | 25 | if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { 26 | flowLayout.headerReferenceSize = CGSize(width: UIScreen.main.bounds.width, height: 50) 27 | flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 28 | flowLayout.sectionHeadersPinToVisibleBounds = true 29 | flowLayout.estimatedItemSize = CGSize( 30 | width: UIScreen.main.bounds.width - 2, 31 | height: 200 32 | ) 33 | flowLayout.invalidateLayout() 34 | } 35 | 36 | collectionView.reloadData() 37 | NotificationCenter.default.addObserver(self, selector: #selector(onDidUpdateBookmarks(_:)), name: .didUpdateBookmarks, object: nil) 38 | checkIfHaveBookmarks() 39 | } 40 | 41 | private func checkIfHaveBookmarks(){ 42 | self.errorTextLabel.isHidden = !(self.videoBookmarks.count == 0 && self.starsBookmarks.count == 0) 43 | self.errorTextLabel.text = "You haven't added any videos or pornstars to your bookmarks yet :(" 44 | } 45 | 46 | @objc func onDidUpdateBookmarks(_ notification: Notification) 47 | { 48 | DispatchQueue.main.async { 49 | self.collectionView.reloadData() 50 | self.checkIfHaveBookmarks() 51 | } 52 | } 53 | 54 | deinit { 55 | NotificationCenter.default.removeObserver(self) 56 | } 57 | } 58 | 59 | extension BookmarksViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 60 | 61 | func numberOfSections(in collectionView: UICollectionView) -> Int { 62 | return 2 63 | } 64 | 65 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 66 | switch kind { 67 | case UICollectionView.elementKindSectionHeader: 68 | 69 | let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TitleSectionHeaderReusableView.className, for: indexPath) as! TitleSectionHeaderReusableView 70 | if indexPath.section == 0 { 71 | headerView.setupTitle(title: self.starsBookmarks.count == 0 ? "" : "Pornstars") 72 | } 73 | else{ 74 | headerView.setupTitle(title: self.videoBookmarks.count == 0 ? "" : "Videos") 75 | } 76 | 77 | 78 | return headerView 79 | 80 | case UICollectionView.elementKindSectionFooter: 81 | return UICollectionReusableView() 82 | 83 | default: 84 | assert(false, "Unexpected element kind") 85 | } 86 | } 87 | 88 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 89 | if section == 0 { 90 | return self.starsBookmarks.count > 0 ? 1 : 0 91 | } 92 | return self.videoBookmarks.count 93 | } 94 | 95 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 96 | if indexPath.section == 0{ 97 | let starCell = collectionView.dequeueReusableCell(withReuseIdentifier: StarsCarouselCollectionViewCell.className, for: indexPath) as! StarsCarouselCollectionViewCell 98 | starCell.setup(stars: self.starsBookmarks, onItemSelect: { index in 99 | let vc = StarViewController() 100 | vc.tabDelegate = self.tabDelegate 101 | vc.star = self.starsBookmarks[index.row] 102 | self.navigationController?.pushViewController(vc, animated: true) 103 | }) 104 | return starCell 105 | } 106 | let videoCell = collectionView.dequeueReusableCell(withReuseIdentifier: VideoCollectionViewCell.className, for: indexPath) as! VideoCollectionViewCell 107 | videoCell.setup(video: self.videoBookmarks[indexPath.row]) 108 | return videoCell 109 | } 110 | 111 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 112 | if indexPath.section == 1 { 113 | VideoPreviewViewController.present(fromView: self, video: self.videoBookmarks[indexPath.row], delegate: self.tabDelegate) 114 | } 115 | } 116 | } 117 | 118 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/BannerCell/BannerCollectionViewCell.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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /ICO-Visualizer/Services/UserPreferences.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserPreferences.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 05/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class UserPreferences{ 12 | static let shared = UserPreferences() 13 | 14 | var reelSource: APIService.ReelSource { 15 | get{ 16 | if let str = UserDefaults.standard.string(forKey: "reelSource"){ 17 | return APIService.ReelSource(rawValue: str) ?? APIService.ReelSource.redgifs 18 | } 19 | return APIService.ReelSource.redgifs 20 | } 21 | set{ 22 | UserDefaults.standard.set(newValue.rawValue, forKey: "reelSource") 23 | } 24 | } 25 | 26 | var isAudioOn: Bool { 27 | get{ 28 | if UserDefaults.standard.object(forKey: "isAudioOn") == nil { 29 | return true 30 | } 31 | return UserDefaults.standard.bool(forKey: "isAudioOn") 32 | } 33 | set{ 34 | UserDefaults.standard.set(newValue, forKey: "isAudioOn") 35 | } 36 | } 37 | 38 | var userPin: String? { 39 | get{ 40 | return UserDefaults.standard.string(forKey: "userPin") 41 | } 42 | set{ 43 | UserDefaults.standard.set(newValue, forKey: "userPin") 44 | } 45 | } 46 | 47 | var userFakePin: String? { 48 | get{ 49 | return UserDefaults.standard.string(forKey: "userFakePin") 50 | } 51 | set{ 52 | UserDefaults.standard.set(newValue, forKey: "userFakePin") 53 | } 54 | } 55 | 56 | var faceIdEnabled: Bool { 57 | get{ 58 | return UserDefaults.standard.bool(forKey: "faceId") 59 | } 60 | set{ 61 | UserDefaults.standard.set(newValue, forKey: "faceId") 62 | } 63 | } 64 | 65 | var starToFind: String? { 66 | get { 67 | return UserDefaults.standard.string(forKey: "starToFind") 68 | } 69 | set{ 70 | UserDefaults.standard.set(newValue, forKey: "starToFind") 71 | } 72 | } 73 | } 74 | 75 | 76 | class UserBookmakrs { 77 | static let shared = UserBookmakrs() 78 | 79 | func saveVideoToBookmark(video: Video){ 80 | if self.checkVideoBookmarksCointain(video){ 81 | return 82 | } 83 | var bookmarks = self.getVideosBookmarks() 84 | bookmarks.append(video) 85 | self.serializeVideosToUserDefaults(bookmarks) 86 | } 87 | 88 | func removeVideoBookmark(video: Video){ 89 | var bookmarks = self.getVideosBookmarks() 90 | bookmarks.removeAll(where: { $0.videoID == video.videoID }) 91 | self.serializeVideosToUserDefaults(bookmarks) 92 | } 93 | 94 | func getVideosBookmarks() -> [Video]{ 95 | do { 96 | if let jsonString = UserDefaults.standard.string(forKey: "videobookmarks")?.data(using: .utf8) { 97 | let result = try JSONDecoder().decode([Video].self, from: jsonString) 98 | return result 99 | } 100 | } 101 | catch{ 102 | print(error) 103 | } 104 | 105 | return [] 106 | } 107 | 108 | 109 | func checkVideoBookmarksCointain(_ video: Video) -> Bool { 110 | return self.getVideosBookmarks().first(where: { $0.videoID == video.videoID }) != nil 111 | } 112 | 113 | private func serializeVideosToUserDefaults(_ videos: [Video]){ 114 | do { 115 | let result = try JSONEncoder().encode(videos) 116 | let resultString = String(data: result, encoding: .utf8) 117 | UserDefaults.standard.set(resultString, forKey: "videobookmarks") 118 | UserDefaults.standard.synchronize() 119 | NotificationCenter.default.post(name: .didUpdateBookmarks, object: nil) 120 | } 121 | catch { 122 | print(error) 123 | } 124 | } 125 | 126 | func saveStarToBookmark(star: Star){ 127 | if self.checkStarBookmarksCointain(star){ 128 | return 129 | } 130 | var bookmarks = self.getStarsBookmarks() 131 | bookmarks.append(star) 132 | self.serializeStarsToUserDefaults(bookmarks) 133 | } 134 | 135 | func removeStarBookmark(star: Star){ 136 | var bookmarks = self.getStarsBookmarks() 137 | bookmarks.removeAll(where: { $0.starName == star.starName }) 138 | self.serializeStarsToUserDefaults(bookmarks) 139 | } 140 | 141 | func getStarsBookmarks() -> [Star]{ 142 | do { 143 | if let jsonString = UserDefaults.standard.string(forKey: "starsbookmarks")?.data(using: .utf8) { 144 | let result = try JSONDecoder().decode([Star].self, from: jsonString) 145 | return result 146 | } 147 | } 148 | catch{ 149 | print(error) 150 | } 151 | 152 | return [] 153 | } 154 | 155 | func checkStarBookmarksCointain(_ star: Star) -> Bool { 156 | return self.getStarsBookmarks().first(where: { $0.starName == star.starName }) != nil 157 | } 158 | 159 | private func serializeStarsToUserDefaults(_ stars: [Star]){ 160 | do { 161 | let result = try JSONEncoder().encode(stars) 162 | let resultString = String(data: result, encoding: .utf8) 163 | UserDefaults.standard.set(resultString, forKey: "starsbookmarks") 164 | UserDefaults.standard.synchronize() 165 | NotificationCenter.default.post(name: .didUpdateBookmarks, object: nil) 166 | } 167 | catch { 168 | print(error) 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/ToggleCell/ToggleCollectionViewCell.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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/NavigationButton/NavigationButtonCollectionViewCell.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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/CategoriesView/CategoriesViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchViewController.swift 3 | // ICO-visualizer 4 | // 5 | // Created by Anonymous on 03/11/21. 6 | // Copyright © 2021 Anonymous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CCBottomRefreshControl 11 | 12 | class CategoriesViewController: BaseViewController { 13 | 14 | private var coordinator: CategoriesViewCoordinator! 15 | 16 | static var currentIndex: Int = 0 17 | 18 | let searchView: UIView = { 19 | let view = UIView() 20 | view.translatesAutoresizingMaskIntoConstraints = false 21 | view.backgroundColor = ColorLayout.default_tab_background 22 | view.setShadowAndCorner(cornerRadius: 8) 23 | return view 24 | }() 25 | 26 | let searchField: UITextField = { 27 | let field = UITextField() 28 | field.translatesAutoresizingMaskIntoConstraints = false 29 | field.returnKeyType = .search 30 | field.keyboardType = .default 31 | field.borderStyle = .none 32 | field.backgroundColor = ColorLayout.default_tab_background 33 | field.placeholder = " Search..." 34 | field.textColor = ColorLayout.default_text 35 | field.attributedPlaceholder = NSAttributedString( 36 | string: " Search...", 37 | attributes: [NSAttributedString.Key.foregroundColor: ColorLayout.default_text] 38 | ) 39 | var imageView = UIImageView(); 40 | var image = UIImage(named: "search_icon") 41 | imageView.image = image; 42 | imageView.tintColor = .lightGray 43 | field.leftView = imageView 44 | field.leftViewMode = UITextField.ViewMode.always 45 | field.leftViewMode = .always 46 | return field 47 | }() 48 | 49 | 50 | 51 | override func viewDidLoad() { 52 | super.viewDidLoad() 53 | 54 | self.view.addSubview(self.searchView) 55 | searchView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true 56 | searchView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true 57 | searchView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true 58 | searchView.heightAnchor.constraint(equalToConstant: 40).isActive = true 59 | 60 | self.searchView.addSubview(searchField) 61 | searchField.trailingAnchor.constraint(equalTo: self.searchView.trailingAnchor, constant: -30).isActive = true 62 | searchField.leadingAnchor.constraint(equalTo: self.searchView.leadingAnchor, constant: 30).isActive = true 63 | searchField.centerYAnchor.constraint(equalTo: self.searchView.centerYAnchor).isActive = true 64 | searchField.delegate = self 65 | 66 | self.collectionView.setupView(self) 67 | if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { 68 | flowLayout.headerReferenceSize = CGSize(width: UIScreen.main.bounds.width, height: 90) 69 | flowLayout.sectionInset = UIEdgeInsets(top: 12, left: 0, bottom: 0, right: 12) 70 | flowLayout.sectionHeadersPinToVisibleBounds = true 71 | flowLayout.estimatedItemSize = CGSize( 72 | width: UIScreen.main.bounds.width - 30, 73 | height: 200 74 | ) 75 | flowLayout.invalidateLayout() 76 | } 77 | coordinator = CategoriesViewCoordinator(self) 78 | let refreshControl = UIRefreshControl() 79 | refreshControl.tintColor = .white 80 | refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged) 81 | collectionView.keyboardDismissMode = .onDrag 82 | collectionView.refreshControl = refreshControl 83 | collectionView.refreshControl?.bounds = CGRect(x: refreshControl.bounds.origin.x, 84 | y: -50, 85 | width: refreshControl.bounds.size.width, 86 | height: refreshControl.bounds.size.height) 87 | self.collectionView.refreshControl?.beginRefreshing() 88 | coordinator.loadData() 89 | 90 | } 91 | 92 | @objc func refresh(_ sender: Any) { 93 | DispatchQueue.main.async { 94 | self.coordinator.categories = [] 95 | self.collectionView.reloadData() 96 | self.coordinator.loadData() 97 | self.collectionView.refreshControl?.beginRefreshing() 98 | } 99 | } 100 | } 101 | 102 | extension CategoriesViewController: UITextFieldDelegate{ 103 | func textFieldShouldReturn(_ textField: UITextField) -> Bool { 104 | self.searchField.resignFirstResponder() 105 | DispatchQueue.main.async { 106 | self.coordinator.filterCategories(filter: textField.text ?? "") 107 | } 108 | return true 109 | } 110 | } 111 | 112 | extension CategoriesViewController: UICollectionViewDelegate, UICollectionViewDataSource { 113 | 114 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 115 | switch kind { 116 | case UICollectionView.elementKindSectionHeader: 117 | 118 | let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TitleSectionHeaderReusableView.className, for: indexPath) as! TitleSectionHeaderReusableView 119 | headerView.setupTitle(title: "Categories") 120 | 121 | return headerView 122 | 123 | case UICollectionView.elementKindSectionFooter: 124 | return UICollectionReusableView() 125 | 126 | default: 127 | assert(false, "Unexpected element kind") 128 | } 129 | } 130 | 131 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 132 | return self.coordinator.categories.count 133 | } 134 | 135 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 136 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TitleCollectionViewCell.className, for: indexPath) as! TitleCollectionViewCell 137 | cell.setup(title: self.coordinator.categories[indexPath.row].category?.capitalizingFirstLetter().replacingOccurrences(of: "-", with: " ") ?? "") 138 | return cell 139 | } 140 | 141 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 142 | if let category = self.coordinator.categories[indexPath.row].category { 143 | if coordinator.filter == "" { 144 | CategoriesViewController.currentIndex = 0 145 | } 146 | else{ 147 | CategoriesViewController.currentIndex = indexPath.row 148 | } 149 | self.tabDelegate?.searchForCategory(category: category) 150 | DispatchQueue.main.async { 151 | self.navigationController?.popViewController(animated: true) 152 | } 153 | } 154 | } 155 | } 156 | 157 | extension CategoriesViewController: CategoriesViewDelegate { 158 | func reloadView() { 159 | DispatchQueue.main.async { 160 | self.collectionView.refreshControl?.endRefreshing() 161 | self.errorTextLabel.isHidden = true 162 | self.collectionView.reloadData() 163 | if CategoriesViewController.currentIndex != 0 { 164 | self.collectionView.scrollToItem(at: IndexPath(row: CategoriesViewController.currentIndex, section: 0), at: .centeredVertically, animated: false) 165 | } 166 | } 167 | } 168 | 169 | func onError(message: Error) { 170 | DispatchQueue.main.async { 171 | self.collectionView.refreshControl?.endRefreshing() 172 | self.errorTextLabel.isHidden = false 173 | self.errorTextLabel.text = message.localizedDescription 174 | } 175 | } 176 | } 177 | 178 | -------------------------------------------------------------------------------- /ICO-Visualizer/Controllers/Cells/StarCell/StarCollectionViewCell.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 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | --------------------------------------------------------------------------------