├── .gitignore ├── .sourcery-version ├── AVCaptureClient ├── .gitignore ├── Package.swift ├── Sources │ └── AVCaptureClient │ │ ├── AVCaptureClient.swift │ │ ├── AVCaptureClientMock.swift │ │ ├── Generated │ │ ├── AutoMockable.generated.swift │ │ └── AutoNullable.generated.swift │ │ ├── ImageUpdater.swift │ │ ├── LiveAVCaptureClient.swift │ │ ├── Sourcery.yml │ │ └── Values.swift └── Tests │ └── AVCaptureClientTests │ └── AVCaptureClientTests.swift ├── Aesthetics ├── .gitignore ├── Package.swift ├── Sources │ └── Aesthetics │ │ ├── Animation.swift │ │ ├── AppIcon.swift │ │ ├── Assets+Typesafe.swift │ │ ├── Color.swift │ │ ├── Fonts+Typesafe.swift │ │ ├── Fonts.swift │ │ ├── GradientMasking.swift │ │ ├── GradientStyling.swift │ │ ├── Resources │ │ ├── Assets.xcassets │ │ │ ├── Contents.json │ │ │ ├── Dark Icons │ │ │ │ ├── Contents.json │ │ │ │ ├── DarkAppIcon.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── DarkAppIconBeige.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── DarkAppIconBeigeNoBlob.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── DarkAppIconBlue.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── DarkAppIconBlueNoBlob.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── DarkAppIconNoBlob.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── DarkAppIconYellow.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ └── DarkAppIconYellowNoBlob.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── IAP Upgrade Examples │ │ │ │ ├── Contents.json │ │ │ │ ├── folia.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── IMG_55323.heic │ │ │ │ ├── monochrome.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── IMG_5531.heic │ │ │ │ └── supergold.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── IMG_5533.heic │ │ │ ├── Light Icons │ │ │ │ ├── AppIconBeige.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── AppIconBeigeNoBlob.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── AppIconBlue.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── AppIconBlueNoBlob.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── AppIconNoBlob.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── AppIconPrimaryHighResolutionPreview.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── AppIconYellow.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ ├── AppIconYellowNoBlob.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── Icon-App-1024x1024.png │ │ │ │ └── Contents.json │ │ │ ├── Phosphor Bold │ │ │ │ ├── Contents.json │ │ │ │ ├── aperture-bold.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── aperture-bold.svg │ │ │ │ ├── circle-dashed-bold.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── circle-dashed-bold.svg │ │ │ │ ├── export-bold.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── export-bold.svg │ │ │ │ ├── heart-straight-bold.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── heart-straight-bold.svg │ │ │ │ ├── mountains-bold.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── mountains-bold.svg │ │ │ │ └── trash-simple-bold.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── trash-simple-bold.svg │ │ │ ├── Phosphor Fill │ │ │ │ ├── Contents.json │ │ │ │ ├── eyedropper-sample-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── eyedropper-sample-fill.svg │ │ │ │ ├── gear-six-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── gear-six-fill.svg │ │ │ │ ├── git-diff-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── git-diff-fill.svg │ │ │ │ ├── heart-straight-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── heart-straight-fill.svg │ │ │ │ ├── layout-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── layout-fill.svg │ │ │ │ ├── lightning-a-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── lightning-a-fill.svg │ │ │ │ ├── lightning-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── lightning-fill.svg │ │ │ │ ├── lightning-slash-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── lightning-slash-fill.svg │ │ │ │ ├── number-square-five-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── number-square-five-fill.svg │ │ │ │ ├── number-square-four-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── number-square-four-fill.svg │ │ │ │ ├── number-square-one-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── number-square-one-fill.svg │ │ │ │ └── number-square-three-fill.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ └── number-square-three-fill.svg │ │ │ └── Phosphor │ │ │ │ ├── Contents.json │ │ │ │ ├── app-store-logo.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── app-store-logo.svg │ │ │ │ ├── article.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── article.svg │ │ │ │ ├── baby.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── baby.svg │ │ │ │ ├── bezier-curve.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── bezier-curve.svg │ │ │ │ ├── circles-four.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── circles-four.svg │ │ │ │ ├── circles-three.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── circles-three.svg │ │ │ │ ├── dots-nine.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── dots-nine.svg │ │ │ │ ├── dots-six.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── dots-six.svg │ │ │ │ ├── eye-slash.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── eye-slash.svg │ │ │ │ ├── flower.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── flower.svg │ │ │ │ ├── globe.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── globe.svg │ │ │ │ ├── grains.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── grains.svg │ │ │ │ ├── grid-four.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── grid-four.svg │ │ │ │ ├── heart-straight.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── heart-straight.svg │ │ │ │ ├── hexagon.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── hexagon.svg │ │ │ │ ├── images.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── images.svg │ │ │ │ ├── intersect.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── intersect.svg │ │ │ │ ├── link-break.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── link-break.svg │ │ │ │ ├── palette.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── palette.svg │ │ │ │ ├── pencil-circle.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── pencil-circle.svg │ │ │ │ ├── prohibit-inset.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── prohibit-inset.svg │ │ │ │ ├── selection-background.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── selection-background.svg │ │ │ │ ├── sun-horizon.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── sun-horizon.svg │ │ │ │ ├── translate.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── translate.svg │ │ │ │ ├── video-camera.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── video-camera.svg │ │ │ │ └── warning-diamond.imageset │ │ │ │ ├── Contents.json │ │ │ │ └── warning-diamond.svg │ │ ├── circular-bold.ttf │ │ └── circular-medium.ttf │ │ ├── SwiftUI Modifiers │ │ ├── View+GradientMask.swift │ │ └── View+ThemedFont.swift │ │ ├── Theme.swift │ │ └── Views │ │ ├── AnthillView.swift │ │ ├── Buttons.swift │ │ ├── LoadingIndicator.swift │ │ ├── SeparatorLine.swift │ │ └── ShadowText.swift └── Tests │ └── AestheticsTests │ └── AestheticsTests.swift ├── CameraFeature ├── .gitignore ├── Package.swift ├── Sources │ └── CameraFeature │ │ ├── AppCaptureIntent.swift │ │ ├── CameraFeature.swift │ │ ├── CameraOverlays.swift │ │ ├── CameraPermissionsView.swift │ │ ├── CameraView.swift │ │ ├── CaptureFormat.swift │ │ ├── LensAdjustmentView.swift │ │ ├── Resources │ │ ├── ar.lproj │ │ │ └── Localizable.strings │ │ ├── cropped.mov │ │ ├── de.lproj │ │ │ └── Localizable.strings │ │ ├── en.lproj │ │ │ └── Localizable.strings │ │ ├── es.lproj │ │ │ └── Localizable.strings │ │ ├── fr.lproj │ │ │ └── Localizable.strings │ │ ├── hr.lproj │ │ │ └── Localizable.strings │ │ ├── ja.lproj │ │ │ └── Localizable.strings │ │ └── pl.lproj │ │ │ └── Localizable.strings │ │ └── StringsLocalized.swift └── Tests │ └── CameraFeatureTests │ └── CameraFeatureTests.swift ├── Common └── Common.h ├── Convenience ├── .gitignore ├── Package.swift ├── Sources │ └── Convenience │ │ └── Either.swift └── Tests │ └── ConvenienceTests │ └── ConvenienceTests.swift ├── Core ├── .gitignore ├── Package.swift ├── Sources │ └── Core │ │ └── CIContext.swift └── Tests │ └── CoreTests │ └── CoreTests.swift ├── DoorbellWidget ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── WidgetBackground.colorset │ │ └── Contents.json ├── Info.plist └── doorbellWidgetBundle.swift ├── ExtensionKit ├── .gitignore ├── Package.swift ├── Sources │ └── ExtensionKit │ │ ├── Bundle+Version.swift │ │ ├── CGFloat+Readability.swift │ │ ├── CaseIterable+Next.swift │ │ ├── Color+Hex.swift │ │ ├── Color+Kelvin.swift │ │ ├── Combine+Task.swift │ │ ├── CoreData+Combine.swift │ │ ├── Device+LacksPhysicalHomeButton.swift │ │ ├── Environment+IsPresentingSheet.swift │ │ ├── ExtensionKit+UIViewRepresented.swift │ │ ├── MacOS.swift │ │ ├── Sequence+Keypaths.swift │ │ ├── SwiftUI+ConditionalModifier.swift │ │ ├── SwiftUI+Frames.swift │ │ ├── SwiftUI+OverlayGeometryReader.swift │ │ ├── UIScreen+ScreenCorners.swift │ │ └── View+PinchToZoom.swift └── Tests │ └── ExtensionKitTests │ └── ExtensionKitTests.swift ├── Gallery ├── .gitignore ├── Package.swift ├── Sources │ └── Gallery │ │ └── Gallery.swift └── Tests │ └── GalleryTests │ └── GalleryTests.swift ├── GalleryFeature ├── .gitignore ├── Package.swift ├── Sources │ └── GalleryFeature │ │ ├── AssetCell.swift │ │ ├── AssetFavouriteEquatable.swift │ │ ├── AssetLayoutStyle.swift │ │ ├── AssetTransitionController.swift │ │ ├── AssetTransitionDriver.swift │ │ ├── AssetTransitioning.swift │ │ ├── AssetViewController.swift │ │ ├── AssetViewRepresentable.swift │ │ ├── AssetsHolder.swift │ │ ├── GalleryDisplayable.swift │ │ ├── GalleryError.swift │ │ ├── GalleryFeature.swift │ │ ├── GalleryOverlays.swift │ │ ├── GalleryPermissionsView.swift │ │ ├── GalleryUndeterminedView.swift │ │ ├── GalleryView.swift │ │ ├── Resources │ │ ├── ar.lproj │ │ │ └── Localizable.strings │ │ ├── de.lproj │ │ │ └── Localizable.strings │ │ ├── en.lproj │ │ │ └── Localizable.strings │ │ ├── es.lproj │ │ │ └── Localizable.strings │ │ ├── fr.lproj │ │ │ └── Localizable.strings │ │ ├── hr.lproj │ │ │ └── Localizable.strings │ │ ├── ja.lproj │ │ │ └── Localizable.strings │ │ └── pl.lproj │ │ │ └── Localizable.strings │ │ ├── StringsLocalized.swift │ │ └── Variables.swift └── Tests │ └── GalleryFeatureTests │ └── GalleryFeatureTests.swift ├── Gemfile ├── Gemfile.lock ├── Haptics ├── .gitignore ├── Package.swift ├── Sources │ └── Haptics │ │ └── Haptics.swift └── Tests │ └── HapticsTests │ └── HapticsTests.swift ├── LICENSE ├── LocationClient ├── .gitignore ├── Package.swift ├── Sources │ └── LocationClient │ │ └── LocationClient.swift └── Tests │ └── LocationClientTests │ └── LocationClientTests.swift ├── Makefile ├── OrientationClient ├── .gitignore ├── Package.swift ├── Sources │ └── OrientationClient │ │ └── OrientationClient.swift └── Tests │ └── OrientationClientTests │ └── OrientationClientTests.swift ├── OverlayView ├── .gitignore ├── Package.swift ├── Sources │ └── OverlayView │ │ ├── OverlayArchitecture.swift │ │ └── OverlayView.swift └── Tests │ └── OverlayViewTests │ └── OverlayViewTests.swift ├── PermissionsClient ├── .gitignore ├── Package.swift ├── Sources │ └── PermissionsClient │ │ ├── Generated │ │ ├── AutoMockable.generated.swift │ │ └── AutoNullable.generated.swift │ │ ├── PermissionsClient+Live.swift │ │ ├── PermissionsClient.swift │ │ ├── PermissionsClientMock.swift │ │ └── Sourcery.yml └── Tests │ └── PermissionsClientTests │ └── PermissionsClientTests.swift ├── Pipeline ├── .gitignore ├── Package.resolved ├── Package.swift ├── Sources │ └── Pipeline │ │ ├── CIFilters.swift │ │ ├── Errors.swift │ │ ├── Filters.swift │ │ ├── Generated │ │ ├── AutoMockable.generated.swift │ │ └── AutoNullable.generated.swift │ │ ├── LUT+Folia.swift │ │ ├── LUT+Helpers.swift │ │ ├── LUT+Mononoke.swift │ │ ├── LUT+MononokeFront.swift │ │ ├── LUT+MononokeFrontTwo.swift │ │ ├── LUT+Supergold.swift │ │ ├── LUT+Vertichrome.swift │ │ ├── MetadataEnricher.swift │ │ ├── Pipeline.swift │ │ ├── Recorder.swift │ │ ├── SoftwareNameEnricher.swift │ │ ├── Sourcery.yml │ │ ├── Transformation.swift │ │ └── Transformers │ │ ├── CubeTransformer.swift │ │ ├── DitheringTransformer.swift │ │ ├── ImagePersistenceTransformer.swift │ │ ├── MonochromeTransformer.swift │ │ └── PolynomialTransformer.swift └── Tests │ └── PipelineTests │ ├── CubeTransformerTests.swift │ ├── MonochromeTransformerTests.swift │ └── Resources │ ├── folia-high-contrast-and-warmth.png │ ├── folia.png │ ├── mononoke-front-v2.png │ ├── mononoke-front.png │ ├── mononoke.png │ ├── portrait.jpg │ ├── prt.png │ ├── still.tiff │ ├── supergold.png │ └── tx.png ├── Preferences ├── .gitignore ├── Package.swift ├── Sources │ └── Preferences │ │ ├── Generated │ │ ├── AutoMockable.generated.swift │ │ └── AutoNullable.generated.swift │ │ ├── Preferences.swift │ │ ├── PreferencesClientMock.swift │ │ └── Sourcery.yml └── Tests │ └── PreferencesTests │ └── PreferencesTests.swift ├── Scripts └── ensure-sourcery-installed.sh ├── Settings ├── .gitignore ├── Package.swift ├── Sources │ └── Settings │ │ ├── Resources │ │ ├── ar.lproj │ │ │ └── Localizable.strings │ │ ├── de.lproj │ │ │ └── Localizable.strings │ │ ├── en.lproj │ │ │ └── Localizable.strings │ │ ├── es.lproj │ │ │ └── Localizable.strings │ │ ├── fr.lproj │ │ │ └── Localizable.strings │ │ ├── hr.lproj │ │ │ └── Localizable.strings │ │ ├── ja.lproj │ │ │ └── Localizable.strings │ │ └── pl.lproj │ │ │ └── Localizable.strings │ │ ├── SettingsError.swift │ │ ├── SettingsFeature.swift │ │ ├── SettingsIconView.swift │ │ ├── SettingsView.swift │ │ └── StringsLocalized.swift └── Tests │ └── SettingsTests │ ├── SettingsTests.swift │ └── __Snapshots__ │ └── SettingsTests │ └── testSettingsScreen.1.png ├── Shared ├── .gitignore ├── Package.swift ├── Sources │ └── Shared │ │ ├── AspectRatio.swift │ │ ├── Box.swift │ │ ├── ChromaticTransformation.swift │ │ ├── Combine+ResultTask.swift │ │ ├── CompositionBlendModes.swift │ │ ├── ContrastPreset.swift │ │ ├── GalleryFilter.swift │ │ ├── GrainPresence.swift │ │ ├── Locales.swift │ │ ├── PHImageManager+Async.swift │ │ ├── Quantization.swift │ │ ├── Schedulers.swift │ │ ├── Screen.swift │ │ ├── Sequence+Keypaths.swift │ │ ├── ShutterStyle.swift │ │ ├── Sourcery │ │ ├── AutoMockable.stencil │ │ ├── AutoNullable.stencil │ │ └── SourceryProtocols.swift │ │ ├── StopsEXIF.swift │ │ ├── TCA+OptionalCache.swift │ │ ├── TemperaturePreset.swift │ │ ├── Vector+Math.swift │ │ ├── VideoView.swift │ │ ├── View+ExtendFrame.swift │ │ ├── View+OnSizeChange.swift │ │ ├── View+Overlay.swift │ │ └── WarholTransformation.swift └── Tests │ └── SharedTests │ └── SharedTests.swift ├── Shoebox ├── .gitignore ├── Package.swift ├── Sources │ └── Shoebox │ │ └── ShoeboxClient.swift └── Tests │ └── ShoeboxTests │ └── ShoeboxTests.swift ├── Shopfront ├── .gitignore ├── Package.swift ├── Sources │ └── Shopfront │ │ ├── Benefits.swift │ │ ├── Errors.swift │ │ ├── Identifiers.swift │ │ ├── Resources │ │ ├── ar.lproj │ │ │ └── Localizable.strings │ │ ├── de.lproj │ │ │ └── Localizable.strings │ │ ├── en.lproj │ │ │ └── Localizable.strings │ │ ├── es.lproj │ │ │ └── Localizable.strings │ │ ├── fr.lproj │ │ │ └── Localizable.strings │ │ ├── hr.lproj │ │ │ └── Localizable.strings │ │ ├── ja.lproj │ │ │ └── Localizable.strings │ │ └── pl.lproj │ │ │ └── Localizable.strings │ │ ├── Shopfront+Environment.swift │ │ ├── Shopfront.storekit │ │ ├── ShopfrontClient.swift │ │ ├── ShopfrontFeature.swift │ │ ├── StringsLocalized.swift │ │ └── UpgradeToProView.swift └── Tests │ └── ShopfrontTests │ └── ShopfrontTests.swift ├── Stops.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ ├── IDEWorkspaceChecks.plist │ ├── WorkspaceSettings.xcsettings │ └── swiftpm │ └── Package.resolved ├── Stops ├── App.swift ├── AppDelegate.swift ├── AppFeature.swift ├── Info.plist ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── Resources │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 180.png │ │ │ ├── 29.png │ │ │ ├── 40.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Dark Icons │ │ │ ├── Contents.json │ │ │ ├── DarkAppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── DarkAppIconBeige.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── DarkAppIconBeigeNoBlob.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── DarkAppIconBlue.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── DarkAppIconBlueNoBlob.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── DarkAppIconNoBlob.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── DarkAppIconYellow.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ └── DarkAppIconYellowNoBlob.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ ├── Light Icons │ │ │ ├── AppIconBeige.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── AppIconBeigeNoBlob.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── AppIconBlue.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── AppIconBlueNoBlob.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── AppIconNoBlob.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── AppIconPrimaryHighResolutionPreview.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── AppIconYellow.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ ├── AppIconYellowNoBlob.appiconset │ │ │ │ ├── Contents.json │ │ │ │ └── Icon-App-1024x1024.png │ │ │ └── Contents.json │ │ └── squarebuttonshadow.imageset │ │ │ ├── Contents.json │ │ │ └── squarebuttonshadow.png │ ├── Launch Screen.storyboard │ ├── ar.lproj │ │ └── Localizable.strings │ ├── de.lproj │ │ └── Localizable.strings │ ├── en.lproj │ │ └── Localizable.strings │ ├── es.lproj │ │ └── Localizable.strings │ ├── fr.lproj │ │ └── Localizable.strings │ ├── hr.lproj │ │ └── Localizable.strings │ ├── ja.lproj │ │ └── Localizable.strings │ └── pl.lproj │ │ └── Localizable.strings ├── Views │ ├── AppView.swift │ ├── CameraControlsView.swift │ ├── HorizontalSwipableView.swift │ ├── Overlays.swift │ └── ShoeboxControlsView.swift └── aperture.entitlements ├── StopsTests ├── __Snapshots__ │ └── apertureTests │ │ └── testScreens.1.png └── apertureTests.swift ├── Views ├── .gitignore ├── Package.swift ├── Sources │ └── Views │ │ ├── CardView.swift │ │ ├── ChunkyButton.swift │ │ ├── EmbossedText.swift │ │ ├── LockedCameraUtils.swift │ │ ├── ProtectedImageView.swift │ │ ├── SealCheckmark.swift │ │ ├── ShareSheet.swift │ │ ├── SquareButton.swift │ │ ├── StarsView.swift │ │ ├── SymmetricStacks.swift │ │ └── TabbedViewControllerRepresentable.swift └── Tests │ └── ViewsTests │ └── ViewsTests.swift ├── VolumeButtonInteractor ├── .gitignore ├── Package.swift ├── Sources │ └── VolumeButtonInteractor │ │ ├── Log.swift │ │ └── VolumeButtonInteractor.swift └── Tests │ └── VolumeButtonInteractorTests │ └── VolumeButtonInteractorTests.swift ├── aperture.app.dSYM.zip ├── fastlane ├── Appfile ├── Fastfile ├── Pluginfile └── README.md └── swiftgen.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/ 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | xcuserdata 12 | *.xccheckout 13 | *.moved-aside 14 | DerivedData 15 | *.hmap 16 | *.ipa 17 | *.cer 18 | 19 | # Swift Package Manager 20 | */.build 21 | */Packages 22 | 23 | # Bundler 24 | vendor/ 25 | 26 | # Fastlane 27 | **/fastlane/report.xml 28 | **/fastlane/Preview.html 29 | **/fastlane/screenshots 30 | **/fastlane/test_output 31 | **/fastlane/.env.default 32 | 33 | # OS X 34 | *.DS_Store 35 | 36 | # Apollo 37 | ApolloCodegen/ApolloCLI/* 38 | -------------------------------------------------------------------------------- /.sourcery-version: -------------------------------------------------------------------------------- 1 | 1.8.2 2 | -------------------------------------------------------------------------------- /AVCaptureClient/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | -------------------------------------------------------------------------------- /AVCaptureClient/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "AVCaptureClient", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library(name: "AVCaptureClient", targets: ["AVCaptureClient"]), 13 | ], 14 | dependencies: [ 15 | .package(name: "OrientationClient", path: "../OrientationClient"), 16 | .package(name: "Shared", path: "../Shared"), 17 | .package(name: "Shopfront", path: "../Shopfront"), 18 | .package(name: "Pipeline", path: "../Pipeline"), 19 | .package(name: "Preferences", path: "../Preferences"), 20 | ], 21 | targets: [ 22 | .target( 23 | name: "AVCaptureClient", 24 | dependencies: [ 25 | .product(name: "OrientationClient", package: "OrientationClient"), 26 | .product(name: "Shared", package: "Shared"), 27 | .product(name: "Shopfront", package: "Shopfront"), 28 | .product(name: "Preferences", package: "Preferences"), 29 | .product(name: "Pipeline", package: "Pipeline"), 30 | ], 31 | swiftSettings: [ 32 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 33 | ], 34 | linkerSettings: [ 35 | .unsafeFlags(["-Xlinker", "-application_extension"]) 36 | ] 37 | ), 38 | .testTarget( 39 | name: "AVCaptureClientTests", 40 | dependencies: ["AVCaptureClient"] 41 | ), 42 | ] 43 | ) 44 | -------------------------------------------------------------------------------- /AVCaptureClient/Sources/AVCaptureClient/AVCaptureClientMock.swift: -------------------------------------------------------------------------------- 1 | import Combine 2 | import Foundation 3 | 4 | extension AVCaptureClientMock { 5 | public convenience init(override: Bool) { 6 | self.init() 7 | self.underlyingPreviewImagePublisher = CurrentValueSubject(AVPreviewImage(rawValue: .init())).eraseToAnyPublisher() 8 | self.underlyingRedactedPreviewImagePublisher = CurrentValueSubject(AVPreviewImage(rawValue: .init())).eraseToAnyPublisher() 9 | self.underlyingIsRunning = false 10 | self.underlyingIsAttemptingToRun = false 11 | self.underlyingCaptureLifecyclePublisher = CurrentValueSubject(.idle).eraseToAnyPublisher() 12 | self.underlyingCapturedImagePublisher = CurrentValueSubject( 13 | .init(identifier: 0, pixelWidth: 100, pixelHeight: 100, position: .front, rawValue: .init()) 14 | ).eraseToAnyPublisher() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /AVCaptureClient/Sources/AVCaptureClient/Generated/AutoNullable.generated.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery 1.8.2 — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | // swiftlint:disable all 4 | 5 | import Foundation 6 | 7 | import Shared 8 | 9 | import Pipeline 10 | 11 | #if canImport(AVFoundation) 12 | import AVFoundation 13 | #endif 14 | 15 | #if canImport(Combine) 16 | import Combine 17 | #endif 18 | 19 | #if canImport(ComposableArchitecture) 20 | import ComposableArchitecture 21 | #endif 22 | 23 | #if canImport(CoreImage) 24 | import CoreImage 25 | #endif 26 | 27 | #if canImport(FoundationNetworking) 28 | import FoundationNetworking 29 | #endif 30 | 31 | #if canImport(UIKit) 32 | import UIKit 33 | #endif 34 | 35 | -------------------------------------------------------------------------------- /AVCaptureClient/Sources/AVCaptureClient/ImageUpdater.swift: -------------------------------------------------------------------------------- 1 | import Combine 2 | import ComposableArchitecture 3 | import Foundation 4 | import SwiftUI 5 | 6 | public class ImageUpdater: ObservableObject { 7 | public static let shared = ImageUpdater() 8 | 9 | @Dependency(\.avCaptureClient) var avCaptureClient 10 | @Dependency(\.pipelineQueue) var pipelineQueue 11 | @Dependency(\.mainQueue) var mainQueue 12 | 13 | @Published public var previewImage: UIImage? 14 | @Published public var redactedPreviewImage: UIImage? 15 | 16 | private var cancellables = Set() 17 | 18 | public init() { 19 | avCaptureClient.previewImagePublisher 20 | .subscribe(on: pipelineQueue) 21 | .receive(on: mainQueue) 22 | .sink(receiveValue: { [weak self] value in 23 | guard let self else { return } 24 | self.previewImage = value.rawValue 25 | }) 26 | .store(in: &cancellables) 27 | 28 | avCaptureClient.redactedPreviewImagePublisher 29 | .subscribe(on: pipelineQueue) 30 | .receive(on: mainQueue) 31 | .sink(receiveValue: { [weak self] value in 32 | guard let self else { return } 33 | self.redactedPreviewImage = value.rawValue 34 | }) 35 | .store(in: &cancellables) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /AVCaptureClient/Sources/AVCaptureClient/Sourcery.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | - "." 3 | templates: 4 | - "../../../Shared/Sources/Shared/Sourcery/AutoMockable.stencil" 5 | - "../../../Shared/Sources/Shared/Sourcery/AutoNullable.stencil" 6 | output: 7 | "./Generated" 8 | args: 9 | importShared: "true" 10 | importPipeline: "true" 11 | -------------------------------------------------------------------------------- /AVCaptureClient/Sources/AVCaptureClient/Values.swift: -------------------------------------------------------------------------------- 1 | import AVFoundation.AVCaptureDevice 2 | import Foundation 3 | import Pipeline 4 | import UIKit 5 | 6 | public enum CaptureLifecycle: Equatable { 7 | case didCapture(Int64) 8 | case idle 9 | case willBeginCapture(Int64) 10 | case willCapture(Int64) 11 | case willBeginRecording 12 | case recording(Measurement) 13 | } 14 | 15 | public struct AVCapturedImage: Equatable { 16 | public let identifier: Int64 17 | public let pixelWidth: Int 18 | public let pixelHeight: Int 19 | public let position: AVCaptureDevice.Position 20 | public let rawValue: Data 21 | } 22 | 23 | public struct AVPreviewImage: Equatable { 24 | public let rawValue: UIImage? 25 | } 26 | 27 | public enum SessionError: Equatable, Error { 28 | case invalidCaptureInput 29 | case invalidCaptureOutput 30 | case missingVideoDevice 31 | case missingAudioDevice 32 | case unableToAddDataConnection 33 | case pipeline(PipelineError) 34 | case invalidRecordingState 35 | } 36 | 37 | public enum SessionState: Equatable { 38 | case idle 39 | case success 40 | case running 41 | case notAuthorized 42 | case error(NSError, Bool) 43 | case unavailable 44 | } 45 | 46 | public enum CaptureError: Error { 47 | case failedToGenerateSettingsForAssetWriter 48 | } 49 | 50 | public enum ZoomDirection { 51 | case tighter 52 | case wider 53 | } 54 | 55 | public enum ZoomLevelDisplayable: Equatable { 56 | case string(String) 57 | case image(UIImage) 58 | } 59 | -------------------------------------------------------------------------------- /AVCaptureClient/Tests/AVCaptureClientTests/AVCaptureClientTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import AVCaptureClient 3 | 4 | final class AVCaptureClientTests: XCTestCase { } 5 | -------------------------------------------------------------------------------- /Aesthetics/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Aesthetics/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Aesthetics", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "Aesthetics", 14 | targets: ["Aesthetics"] 15 | ), 16 | ], 17 | dependencies: [ 18 | .package( 19 | name: "ExtensionKit", 20 | path: "../ExtensionKit" 21 | ), 22 | ], 23 | targets: [ 24 | .target( 25 | name: "Aesthetics", 26 | dependencies: [ 27 | .product( 28 | name: "ExtensionKit", 29 | package: "ExtensionKit" 30 | ), 31 | ], 32 | resources: [ 33 | .process("Resources") 34 | ], 35 | swiftSettings: [ 36 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 37 | ], 38 | linkerSettings: [ 39 | .unsafeFlags(["-Xlinker", "-application_extension"]) 40 | ] 41 | ), 42 | .testTarget( 43 | name: "AestheticsTests", 44 | dependencies: ["Aesthetics"] 45 | ), 46 | ] 47 | ) 48 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Animation.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | extension Animation { 5 | static public var springable: Animation { 6 | return .spring( 7 | response: 0.45, 8 | dampingFraction: 0.65 9 | ) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Color.swift: -------------------------------------------------------------------------------- 1 | import ExtensionKit 2 | import SwiftUI 3 | 4 | public extension Color { 5 | static var armyGreen: Color { Color(hex: 0x459A70) } 6 | static var banana: Color { Color(hex: 0xF2B33E) } 7 | static var bubblegum: Color { Color(hex: 0xF095A6) } 8 | static var forestGreen: Color { Color(hex: 0x235347) } 9 | static var olive: Color { Color(hex: 0x9EA03B) } 10 | static var punchyRed: Color { Color(hex: 0xDB2F3C) } 11 | static var seaBlue: Color { Color(hex: 0x1F41D6) } 12 | static var seaSalt: Color { Color(hex: 0xE0E0DF) } 13 | static var simpsons: Color { Color(hex: 0xF5CA44) } 14 | static var watermelon: Color { Color(hex: 0xFF0455) } 15 | 16 | static var gameboyBoy: Color { Color(hex: 0x5090F1) } 17 | static var gameboyGreen: Color { Color(hex: 0x62B852) } 18 | static var gameboyPurple: Color { Color(hex: 0xF4B9F7) } 19 | static var gameboyRed: Color { Color(hex: 0xED714B) } 20 | static var gameboyYellow: Color { Color(hex: 0xF9D96D) } 21 | } 22 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Fonts.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public extension SwiftUI.Font { 5 | static func registerCustomFonts() { 6 | for url in Bundle.module.urls(forResourcesWithExtension: "ttf", subdirectory: nil) ?? [] { 7 | CTFontManagerRegisterFontsForURL(url as CFURL, .process, nil) 8 | } 9 | 10 | for url in Bundle.module.urls(forResourcesWithExtension: "otf", subdirectory: nil) ?? [] { 11 | CTFontManagerRegisterFontsForURL(url as CFURL, .process, nil) 12 | } 13 | } 14 | } 15 | 16 | public extension View { 17 | func registerCustomFonts() -> Self { 18 | SwiftUI.Font.registerCustomFonts() 19 | return self 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/GradientMasking.swift: -------------------------------------------------------------------------------- 1 | import ExtensionKit 2 | import SwiftUI 3 | 4 | public extension View { 5 | @ViewBuilder func gradientForeground(_ styling: GradientStyling) -> some View { 6 | gradientForegroundMask([styling.topColor, styling.bottomColor]) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIcon.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIcon.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeige.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeige.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeige.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeigeNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeigeNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeigeNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlue.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlue.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlue.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlueNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlueNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlueNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellow.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellow.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellow.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellowNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellowNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellowNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/folia.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "IMG_55323.heic", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/folia.imageset/IMG_55323.heic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/folia.imageset/IMG_55323.heic -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/monochrome.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "IMG_5531.heic", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/monochrome.imageset/IMG_5531.heic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/monochrome.imageset/IMG_5531.heic -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/supergold.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "IMG_5533.heic", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/supergold.imageset/IMG_5533.heic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/IAP Upgrade Examples/supergold.imageset/IMG_5533.heic -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBeige.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBeige.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBeige.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBeigeNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBeigeNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBeigeNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBlue.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBlue.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBlue.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBlueNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBlueNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconBlueNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconPrimaryHighResolutionPreview.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconPrimaryHighResolutionPreview.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconPrimaryHighResolutionPreview.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconYellow.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconYellow.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconYellow.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconYellowNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconYellowNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/AppIconYellowNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Light Icons/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/aperture-bold.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "aperture-bold.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/aperture-bold.imageset/aperture-bold.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/circle-dashed-bold.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "circle-dashed-bold.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/circle-dashed-bold.imageset/circle-dashed-bold.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/export-bold.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "export-bold.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/export-bold.imageset/export-bold.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/heart-straight-bold.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "heart-straight-bold.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/heart-straight-bold.imageset/heart-straight-bold.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/mountains-bold.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mountains-bold.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/mountains-bold.imageset/mountains-bold.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/trash-simple-bold.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "trash-simple-bold.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Bold/trash-simple-bold.imageset/trash-simple-bold.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/eyedropper-sample-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "eyedropper-sample-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/eyedropper-sample-fill.imageset/eyedropper-sample-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/gear-six-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "gear-six-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/gear-six-fill.imageset/gear-six-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/git-diff-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "git-diff-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/git-diff-fill.imageset/git-diff-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/heart-straight-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "heart-straight-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/heart-straight-fill.imageset/heart-straight-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/layout-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "layout-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/layout-fill.imageset/layout-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/lightning-a-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "lightning-a-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/lightning-a-fill.imageset/lightning-a-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/lightning-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "lightning-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/lightning-fill.imageset/lightning-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/lightning-slash-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "lightning-slash-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/lightning-slash-fill.imageset/lightning-slash-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/number-square-five-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "number-square-five-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/number-square-five-fill.imageset/number-square-five-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/number-square-four-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "number-square-four-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/number-square-four-fill.imageset/number-square-four-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/number-square-one-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "number-square-one-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/number-square-one-fill.imageset/number-square-one-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/number-square-three-fill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "number-square-three-fill.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor Fill/number-square-three-fill.imageset/number-square-three-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/app-store-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "app-store-logo.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/app-store-logo.imageset/app-store-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/article.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "article.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/article.imageset/article.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/baby.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "baby.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/baby.imageset/baby.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/bezier-curve.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "bezier-curve.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/bezier-curve.imageset/bezier-curve.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/circles-four.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "circles-four.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/circles-four.imageset/circles-four.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/circles-three.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "circles-three.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/circles-three.imageset/circles-three.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/dots-nine.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "dots-nine.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/dots-nine.imageset/dots-nine.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/dots-six.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "dots-six.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/dots-six.imageset/dots-six.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/eye-slash.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "eye-slash.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/eye-slash.imageset/eye-slash.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/flower.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "flower.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/flower.imageset/flower.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/globe.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "globe.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/globe.imageset/globe.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/grains.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "grains.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/grains.imageset/grains.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/grid-four.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "grid-four.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/grid-four.imageset/grid-four.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/heart-straight.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "heart-straight.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/heart-straight.imageset/heart-straight.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/hexagon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "hexagon.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/hexagon.imageset/hexagon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/images.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "images.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/images.imageset/images.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/intersect.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "intersect.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/intersect.imageset/intersect.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/link-break.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "link-break.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/link-break.imageset/link-break.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/palette.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "palette.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/palette.imageset/palette.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/pencil-circle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "pencil-circle.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/pencil-circle.imageset/pencil-circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/prohibit-inset.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "prohibit-inset.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/prohibit-inset.imageset/prohibit-inset.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/selection-background.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "selection-background.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/selection-background.imageset/selection-background.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/sun-horizon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "sun-horizon.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/sun-horizon.imageset/sun-horizon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/translate.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "translate.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/translate.imageset/translate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/video-camera.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "video-camera.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/video-camera.imageset/video-camera.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/warning-diamond.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "warning-diamond.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets/Phosphor/warning-diamond.imageset/warning-diamond.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/circular-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/circular-bold.ttf -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Resources/circular-medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Aesthetics/Sources/Aesthetics/Resources/circular-medium.ttf -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/SwiftUI Modifiers/View+GradientMask.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | extension View { 4 | func gradientForegroundMask(_ colors: [Color]) -> some View { 5 | self.overlay( 6 | LinearGradient( 7 | gradient: Gradient( 8 | colors: colors 9 | ), 10 | startPoint: .top, 11 | endPoint: .bottom 12 | ) 13 | ) 14 | .mask(self) 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/SwiftUI Modifiers/View+ThemedFont.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public extension View { 4 | func boldThemedFont(size: CGFloat) -> some View { 5 | self 6 | .font(.custom(FontFamily.CircularStd.bold, size: size)) 7 | } 8 | 9 | func mediumThemedFont(size: CGFloat) -> some View { 10 | self 11 | .font(.custom(FontFamily.CircularStd.medium, size: size)) 12 | } 13 | 14 | func themedFont(size: CGFloat) -> some View { 15 | self 16 | .font(.custom("Circular Std", size: size)) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Views/AnthillView.swift: -------------------------------------------------------------------------------- 1 | import ExtensionKit 2 | import Foundation 3 | import SwiftUI 4 | 5 | public struct AnthillView: View { 6 | @State private var phase: CGFloat = 0 7 | private let color: Color 8 | 9 | public init(color: Color) { 10 | self.color = color 11 | } 12 | 13 | public var body: some View { 14 | Rectangle() 15 | .strokeBorder(style: StrokeStyle(lineWidth: 4, dash: [10], dashPhase: phase)) 16 | .foregroundColor(color) 17 | .onAppear { 18 | withAnimation(.linear.repeatForever(autoreverses: false)) { 19 | phase += 20 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Views/LoadingIndicator.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public struct LoadingIndicator: View { 5 | public var body: some View { 6 | Image(systemName: "sun.min.fill") 7 | .resizable() 8 | .blendMode(.difference) 9 | .rotationEffect(Angle(degrees: self.isAnimating ? 360.0 : 0.0)) 10 | .animation( 11 | Animation 12 | .linear(duration: 12.0) 13 | .repeatForever(autoreverses: false), 14 | value: isAnimating 15 | ) 16 | .onAppear { 17 | isAnimating = true 18 | } 19 | } 20 | 21 | @State var isAnimating = false 22 | 23 | public init() { } 24 | } 25 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Views/SeparatorLine.swift: -------------------------------------------------------------------------------- 1 | import ExtensionKit 2 | import SwiftUI 3 | 4 | @ViewBuilder 5 | public func separator(_ theme: Theme) -> some View { 6 | let separatorPrimaryColor = Color.black 7 | let separatorSecondaryColor = Color(theme.cardBorderStripColor) 8 | 9 | ZStack(alignment: .center) { 10 | VStack(alignment: .center, spacing: 0) { 11 | Rectangle() 12 | .fill(separatorPrimaryColor) 13 | .frame( 14 | width: UIScreen.main.bounds.size.width, 15 | height: 2.0, 16 | alignment: .center 17 | ) 18 | 19 | Rectangle() 20 | .fill(separatorSecondaryColor) 21 | .frame( 22 | width: UIScreen.main.bounds.size.width - 2.0, 23 | height: 1.0, 24 | alignment: .center 25 | ) 26 | } 27 | } 28 | .frame( 29 | height: 4, 30 | alignment: .center 31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /Aesthetics/Sources/Aesthetics/Views/ShadowText.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public struct ShadowText: View { 5 | 6 | let string: String 7 | let shadowColor: Color 8 | 9 | public init(_ string: String, _ shadowColor: Color) { 10 | self.string = string 11 | self.shadowColor = shadowColor 12 | } 13 | 14 | public var body: some View { 15 | ZStack { 16 | Text(string) 17 | .offset(y: 1.5) 18 | .foregroundColor(shadowColor) 19 | 20 | Text(string) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Aesthetics/Tests/AestheticsTests/AestheticsTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Aesthetics 3 | 4 | final class AestheticsTests: XCTestCase { 5 | func testExample() throws { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(Aesthetics().text, "Hello, World!") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /CameraFeature/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | -------------------------------------------------------------------------------- /CameraFeature/Sources/CameraFeature/AppCaptureIntent.swift: -------------------------------------------------------------------------------- 1 | import AppIntents 2 | import AVFoundation 3 | import Foundation 4 | 5 | public enum CameraPosition: String, Codable { 6 | case front 7 | case back 8 | 9 | var avFoundationPosition: AVCaptureDevice.Position { 10 | switch self { 11 | case .front: 12 | return .front 13 | case .back: 14 | return .back 15 | } 16 | } 17 | } 18 | 19 | @available(iOS 18, *) 20 | public struct AppCaptureIntent: CameraCaptureIntent { 21 | public struct MyAppContext: Codable { 22 | var cameraPosition: CameraPosition = .back 23 | } 24 | 25 | public typealias AppContext = MyAppContext 26 | 27 | public static let title: LocalizedStringResource = "AppCaptureIntent" 28 | public static let description = IntentDescription("Capture photos with MyApp.") 29 | 30 | public init() { } 31 | 32 | @MainActor 33 | public func perform() async throws -> some IntentResult { 34 | return .result() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CameraFeature/Sources/CameraFeature/CaptureFormat.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum CaptureFormat { 4 | case photo 5 | case video 6 | } 7 | -------------------------------------------------------------------------------- /CameraFeature/Sources/CameraFeature/Resources/cropped.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/CameraFeature/Sources/CameraFeature/Resources/cropped.mov -------------------------------------------------------------------------------- /CameraFeature/Tests/CameraFeatureTests/CameraFeatureTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | final class Tests: XCTestCase { } 4 | -------------------------------------------------------------------------------- /Common/Common.h: -------------------------------------------------------------------------------- 1 | // 2 | // Common.h 3 | // Common 4 | // 5 | // Created by Rehat Kathuria on 07/11/2022. 6 | // 7 | 8 | #import 9 | 10 | //! Project version number for Common. 11 | FOUNDATION_EXPORT double CommonVersionNumber; 12 | 13 | //! Project version string for Common. 14 | FOUNDATION_EXPORT const unsigned char CommonVersionString[]; 15 | 16 | // In this header, you should import all the public headers of your framework using statements like #import 17 | 18 | 19 | -------------------------------------------------------------------------------- /Convenience/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | -------------------------------------------------------------------------------- /Convenience/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Convenience", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "Convenience", 14 | targets: ["Convenience"] 15 | ), 16 | ], 17 | dependencies: [], 18 | targets: [ 19 | .target( 20 | name: "Convenience", 21 | dependencies: [], 22 | swiftSettings: [ 23 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 24 | ], 25 | linkerSettings: [ 26 | .unsafeFlags(["-Xlinker", "-application_extension"]) 27 | ] 28 | ), 29 | .testTarget( 30 | name: "ConvenienceTests", 31 | dependencies: ["Convenience"] 32 | ), 33 | ] 34 | ) 35 | -------------------------------------------------------------------------------- /Convenience/Tests/ConvenienceTests/ConvenienceTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Convenience 3 | 4 | final class ConvenienceTests: XCTestCase { } 5 | -------------------------------------------------------------------------------- /Core/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Core/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Core", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "Core", 14 | targets: ["Core"] 15 | ), 16 | ], 17 | dependencies: [ 18 | .package(name: "Shared", path: "../Shared"), 19 | ], 20 | targets: [ 21 | .target( 22 | name: "Core", 23 | dependencies: [ 24 | .product(name: "Shared", package: "Shared"), 25 | ], 26 | swiftSettings: [ 27 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 28 | ], 29 | linkerSettings: [ 30 | .unsafeFlags(["-Xlinker", "-application_extension"]) 31 | ] 32 | ), 33 | .testTarget( 34 | name: "CoreTests", 35 | dependencies: ["Core"] 36 | ), 37 | ] 38 | ) 39 | -------------------------------------------------------------------------------- /Core/Sources/Core/CIContext.swift: -------------------------------------------------------------------------------- 1 | import CoreImage 2 | import Dependencies 3 | import Foundation 4 | 5 | public let ciContext: CIContext = { 6 | if let device = MTLCreateSystemDefaultDevice() { 7 | return CIContext(mtlDevice: device) 8 | } else { 9 | return CIContext() 10 | } 11 | }() 12 | 13 | private enum CIContextKey: DependencyKey { 14 | static let liveValue: CIContext = ciContext 15 | static var testValue: CIContext = CIContext() 16 | } 17 | 18 | public extension DependencyValues { 19 | var ciContext: CIContext { 20 | get { self[CIContextKey.self] } 21 | set { self[CIContextKey.self] = newValue } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Core/Tests/CoreTests/CoreTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Core 3 | 4 | final class CoreTests: XCTestCase { 5 | func testExample() throws { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(Core().text, "Hello, World!") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DoorbellWidget/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DoorbellWidget/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /DoorbellWidget/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /DoorbellWidget/Assets.xcassets/WidgetBackground.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /DoorbellWidget/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.widgetkit-extension 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /DoorbellWidget/doorbellWidgetBundle.swift: -------------------------------------------------------------------------------- 1 | import CameraFeature 2 | import SwiftUI 3 | import WidgetKit 4 | 5 | @main 6 | struct doorbellWidgetBundle: WidgetBundle { 7 | var body: some Widget { 8 | if #available(iOS 18, *) { 9 | LockedWidgetControl() 10 | } 11 | } 12 | } 13 | 14 | @available(iOS 18, *) 15 | struct LockedWidgetControl: ControlWidget { 16 | var body: some ControlWidgetConfiguration { 17 | StaticControlConfiguration( 18 | kind: "com.eff.corp.aperture.doorbell.widget.control" 19 | ) { 20 | ControlWidgetButton(action: AppCaptureIntent()) { 21 | Label("Launch App", systemImage: "camera.shutter.button") 22 | } 23 | } 24 | .displayName("Launch Camera") 25 | .description("Launch the camera for Stops") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ExtensionKit/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | -------------------------------------------------------------------------------- /ExtensionKit/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "ExtensionKit", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "ExtensionKit", 14 | targets: ["ExtensionKit"] 15 | ) 16 | ], 17 | dependencies: [ 18 | .package(name: "Shared", path: "../Shared"), 19 | ], 20 | targets: [ 21 | .target( 22 | name: "ExtensionKit", 23 | dependencies: [ 24 | .product(name: "Shared", package: "Shared"), 25 | ], 26 | swiftSettings: [ 27 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 28 | ], 29 | linkerSettings: [ 30 | .unsafeFlags(["-Xlinker", "-application_extension"]) 31 | ] 32 | ), 33 | .testTarget( 34 | name: "ExtensionKitTests", 35 | dependencies: ["ExtensionKit"] 36 | ) 37 | ] 38 | ) 39 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/Bundle+Version.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Bundle { 4 | private var releaseVersionNumber: String? { 5 | infoDictionary?["CFBundleShortVersionString"] as? String 6 | } 7 | var releaseVersion: String { 8 | "v\(releaseVersionNumber ?? "1.0.0")" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/CGFloat+Readability.swift: -------------------------------------------------------------------------------- 1 | #if os(macOS) 2 | import AppKit 3 | #else 4 | import UIKit 5 | #endif 6 | 7 | public extension CGFloat { 8 | var oneTenth: CGFloat { return self * 0.10 } 9 | var twoTenths: CGFloat { return self * 0.20 } 10 | var quarter: CGFloat { return self * 0.25 } 11 | var threeTenths: CGFloat { return self * 0.30 } 12 | var fourTenths: CGFloat { return self * 0.40 } 13 | var half: CGFloat { return self * 0.5 } 14 | var sixTenths: CGFloat { return self * 0.60 } 15 | var sevenTenths: CGFloat { return self * 0.70 } 16 | var threeQuarters: CGFloat { return self * 0.75 } 17 | var eightTenths: CGFloat { return self * 0.80 } 18 | var nineTenths: CGFloat { return self * 0.90 } 19 | var double: CGFloat { return self * 2.0 } 20 | } 21 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/CaseIterable+Next.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension CaseIterable where Self: Equatable { 4 | func next() -> Self { 5 | let all = Self.allCases 6 | let idx = all.firstIndex(of: self)! 7 | let next = all.index(after: idx) 8 | return all[next == all.endIndex ? all.startIndex : next] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/Color+Hex.swift: -------------------------------------------------------------------------------- 1 | #if os(macOS) 2 | #else 3 | import UIKit 4 | #endif 5 | 6 | import SwiftUI 7 | 8 | public extension Color { 9 | init(hex: UInt, alpha: Double = 1) { 10 | self.init( 11 | .sRGB, 12 | red: Double((hex >> 16) & 0xff) / 255, 13 | green: Double((hex >> 08) & 0xff) / 255, 14 | blue: Double((hex >> 00) & 0xff) / 255, 15 | opacity: alpha 16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/Combine+Task.swift: -------------------------------------------------------------------------------- 1 | import ComposableArchitecture 2 | import Foundation 3 | 4 | public extension Effect { 5 | static func resultTask( 6 | priority: TaskPriority? = nil, 7 | operation: @escaping @Sendable () async -> Result 8 | ) -> Self { 9 | Effect, Never> 10 | .task(priority: priority, operation: operation) 11 | .flatMap { result -> Self in 12 | switch result { 13 | case .success(let value): return Effect(value: value) 14 | case .failure(let error): return Effect(error: error) 15 | } 16 | } 17 | .eraseToEffect() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/Device+LacksPhysicalHomeButton.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | import UIKit 4 | 5 | private struct LacksPhysicalHomeButton: EnvironmentKey { 6 | static public let defaultValue = UIDevice.current.lacksPhysicalHomeButton 7 | } 8 | 9 | public extension EnvironmentValues { 10 | var lacksPhysicalHomeButton: Bool { 11 | get { self[LacksPhysicalHomeButton.self] } 12 | set { self[LacksPhysicalHomeButton.self] = newValue } 13 | } 14 | } 15 | 16 | extension UIDevice { 17 | var lacksPhysicalHomeButton: Bool { 18 | // #if !CAPTURE_EXTENSION 19 | // if #available(iOS 13.0, *) { 20 | // let scenes = UIApplication.shared.connectedScenes 21 | // let windowScene = scenes.first as? UIWindowScene 22 | // guard let window = windowScene?.windows.first else { return false } 23 | // 24 | // return window.safeAreaInsets.top > 20 25 | // } 26 | // 27 | // if #available(iOS 11.0, *), UIApplication.shared.windows.indices.contains(0) { 28 | // return UIApplication.shared.windows[0].safeAreaInsets.top > 20 29 | // } else { 30 | // // Fallback on earlier versions 31 | // return false 32 | // } 33 | // #else 34 | return true 35 | // #endif 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/Environment+IsPresentingSheet.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public struct IsPresentingSheet: EnvironmentKey { 5 | static public let defaultValue = Bool(false) 6 | } 7 | 8 | public extension EnvironmentValues { 9 | var isPresentingSheet: Bool { 10 | get { self[IsPresentingSheet.self] } 11 | set { self[IsPresentingSheet.self] = newValue } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/ExtensionKit+UIViewRepresented.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | #if !os(macOS) 3 | import UIKit 4 | 5 | public struct UIViewRepresented: UIViewRepresentable where UIViewType: UIView { 6 | public let makeUIView: (Context) -> UIViewType 7 | public let updateUIView: (UIViewType, Context) -> Void = { _, _ in } 8 | 9 | public func makeUIView(context: Context) -> UIViewType { 10 | self.makeUIView(context) 11 | } 12 | 13 | public func updateUIView(_ uiView: UIViewType, context: Context) { 14 | self.updateUIView(uiView, context) 15 | } 16 | 17 | public init(_ make: @escaping (Context) -> UIViewType) { self.makeUIView = make } 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/MacOS.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | #if os(macOS) 4 | import Cocoa 5 | 6 | public typealias UIImage = NSImage 7 | public typealias UIScreen = NSScreen 8 | public typealias UIColor = NSColor 9 | public typealias UUID = NSUUID 10 | 11 | public extension NSImage { 12 | var cgImage: CGImage? { 13 | var proposedRect = CGRect( 14 | origin: .zero, 15 | size: size 16 | ) 17 | 18 | return cgImage( 19 | forProposedRect: &proposedRect, 20 | context: nil, 21 | hints: nil 22 | ) 23 | } 24 | } 25 | 26 | public extension Optional where Wrapped == NSScreen { 27 | var scale: CGFloat { 28 | self?.backingScaleFactor ?? 1 29 | } 30 | } 31 | 32 | public extension Image { 33 | init(img: UIImage) { 34 | self.init(nsImage: img) 35 | } 36 | } 37 | 38 | #else 39 | 40 | import UIKit 41 | 42 | public extension Image { 43 | init(img: UIImage) { 44 | self.init(uiImage: img) 45 | } 46 | } 47 | #endif 48 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/Sequence+Keypaths.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Sequence { 4 | func sorted(by keyPath: KeyPath) -> [Element] { 5 | return sorted { a, b in 6 | return a[keyPath: keyPath] < b[keyPath: keyPath] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/SwiftUI+ConditionalModifier.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public extension View { 4 | @ViewBuilder 5 | func `if`(_ condition: Bool, _ modifier: (Self) -> Result) -> some View { 6 | if condition { 7 | modifier(self) 8 | } else { 9 | self 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/SwiftUI+Frames.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public extension View { 4 | func frame(dimension: CGFloat?) -> some View { 5 | frame(width: dimension, height: dimension) 6 | } 7 | 8 | func frame(size: CGSize) -> some View { 9 | frame(width: size.width, height: size.height) 10 | } 11 | 12 | func maxSizeInfinity() -> some View { 13 | frame( 14 | maxWidth: .infinity, 15 | maxHeight: .infinity 16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/SwiftUI+OverlayGeometryReader.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | fileprivate struct SizeKey: PreferenceKey { 4 | static var defaultValue: CGSize { .zero } 5 | 6 | static func reduce(value: inout CGSize, nextValue: () -> CGSize) { 7 | value = nextValue() 8 | } 9 | } 10 | 11 | public extension View { 12 | func geometricSize(_ onChange: @escaping (CGSize) -> ()) -> some View { 13 | overlay { 14 | GeometryReader { proxy in 15 | Color.clear.preference(key: SizeKey.self, value: proxy.size) 16 | } 17 | .onPreferenceChange(SizeKey.self, perform: onChange) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ExtensionKit/Sources/ExtensionKit/UIScreen+ScreenCorners.swift: -------------------------------------------------------------------------------- 1 | #if !os(macOS) 2 | import UIKit 3 | 4 | // https://github.com/kylebshr/ScreenCorners/blob/main/Sources/ScreenCorners/UIScreen%2BScreenCorners.swift 5 | public extension UIScreen { 6 | private static let cornerRadiusKey: String = { 7 | let components = ["Radius", "Corner", "display", "_"] 8 | return components.reversed().joined() 9 | }() 10 | 11 | /// The corner radius of the display. Uses a private property of `UIScreen`, 12 | /// and may report 0 if the API changes. 13 | var displayCornerRadius: CGFloat { 14 | guard let cornerRadius = self.value(forKey: Self.cornerRadiusKey) as? CGFloat else { 15 | return 0 16 | } 17 | return cornerRadius 18 | } 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /ExtensionKit/Tests/ExtensionKitTests/ExtensionKitTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import ExtensionKit 3 | 4 | final class ExtensionKitTests: XCTestCase { } 5 | -------------------------------------------------------------------------------- /Gallery/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Gallery/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.7 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Gallery", 7 | products: [ 8 | .library( 9 | name: "Gallery", 10 | targets: ["Gallery"] 11 | ), 12 | ], 13 | dependencies: [ 14 | ], 15 | targets: [ 16 | .target( 17 | name: "Gallery", 18 | dependencies: [] 19 | ), 20 | .testTarget( 21 | name: "GalleryTests", 22 | dependencies: ["Gallery"] 23 | ), 24 | ] 25 | ) 26 | -------------------------------------------------------------------------------- /Gallery/Sources/Gallery/Gallery.swift: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Gallery/Tests/GalleryTests/GalleryTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Gallery 3 | 4 | final class GalleryTests: XCTestCase { } 5 | -------------------------------------------------------------------------------- /GalleryFeature/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/AssetFavouriteEquatable.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Photos 3 | 4 | public struct AssetFavouriteEquatable: Equatable { 5 | public static func ==(lhs: AssetFavouriteEquatable, rhs: AssetFavouriteEquatable) -> Bool { 6 | lhs.rawValue.localIdentifier == rhs.rawValue.localIdentifier && 7 | lhs.rawValue.isFavorite == rhs.rawValue.isFavorite 8 | } 9 | 10 | public let rawValue: PHAsset 11 | } 12 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/AssetLayoutStyle.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import UIKit.UICollectionView 3 | 4 | enum AssetLayoutStyle { 5 | case grid 6 | case detailed 7 | 8 | func recalculate(layout: UICollectionViewFlowLayout, inBoundingSize size: CGSize) { 9 | switch self { 10 | case .grid: 11 | layout.minimumLineSpacing = 15 12 | layout.minimumInteritemSpacing = 1 13 | layout.sectionInset = UIEdgeInsets.init(top: 15, left: 15, bottom: 15, right: 15) 14 | let width = (size.width / 2.5) - (15 * 3) 15 | layout.itemSize = .init( 16 | width: width, 17 | height: width 18 | ) 19 | case .detailed: 20 | layout.minimumLineSpacing = 0 21 | layout.minimumInteritemSpacing = 0 22 | layout.sectionInset = UIEdgeInsets.zero 23 | layout.scrollDirection = .horizontal; 24 | layout.itemSize = size 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/AssetTransitioning.swift: -------------------------------------------------------------------------------- 1 | import Convenience 2 | import UIKit 3 | import Photos 4 | 5 | class AssetTransitionItem: NSObject { 6 | var initialFrame: CGRect 7 | var image: UIImage { 8 | didSet { 9 | imageView?.image = image 10 | } 11 | } 12 | var indexPath: IndexPath 13 | var object: GalleryDisplayable 14 | var targetFrame: CGRect? 15 | var imageView: UIImageView? 16 | var touchOffset: CGVector = CGVector.zero 17 | 18 | init( 19 | initialFrame: CGRect, 20 | image: UIImage, 21 | indexPath: IndexPath, 22 | object: GalleryDisplayable 23 | ) { 24 | self.initialFrame = initialFrame 25 | self.image = image 26 | self.indexPath = indexPath 27 | self.object = object 28 | super.init() 29 | } 30 | } 31 | 32 | protocol AssetTransitioning { 33 | func itemsForTransition(context: UIViewControllerContextTransitioning) -> Array 34 | func targetFrame(transitionItem: AssetTransitionItem) -> CGRect? 35 | func willTransition(fromController: UIViewController, toController: UIViewController, items: Array) 36 | func didTransition(fromController: UIViewController, toController: UIViewController, items: Array) 37 | } 38 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/GalleryDisplayable.swift: -------------------------------------------------------------------------------- 1 | import Convenience 2 | import Foundation 3 | import Photos 4 | import UIKit 5 | 6 | public typealias GalleryDisplayable = PHAsset 7 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/GalleryError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum GalleryError: Error { 4 | case failedToDecode 5 | } 6 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/GalleryView.swift: -------------------------------------------------------------------------------- 1 | import Aesthetics 2 | import ComposableArchitecture 3 | import Foundation 4 | import SwiftUI 5 | import Views 6 | 7 | public struct GalleryView: View { 8 | 9 | let store: StoreOf 10 | @Environment(\.shutterStyle) var shutterStyle 11 | 12 | public init(store: StoreOf) { self.store = store } 13 | 14 | public var body: some View { 15 | WithViewStore(store) { viewStore in 16 | Group { 17 | AssetViewRepresentable(store: store, shutterStyle: shutterStyle) 18 | } 19 | .overlay(isShown: viewStore.permissionsNotGranted, { 20 | GalleryUndeterminedView(store: store) 21 | }) 22 | .sheet( 23 | item: viewStore.binding( 24 | get: \.assetImageToShare, 25 | send: GalleryFeature.Action.setAssetShareSheetImage 26 | ) 27 | ) { image in 28 | ShareSheet(activityItems: [image]) { completed in 29 | viewStore.send(.setShouldPresentShareSheet(false)) 30 | } 31 | .presentationDetents([.medium]) 32 | .edgesIgnoringSafeArea(.all) 33 | } 34 | .onAppear { viewStore.send(.didAppear) } 35 | } 36 | } 37 | } 38 | 39 | extension UIImage: Identifiable { } 40 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/Resources/ar.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Gallery Permissions" = "السماح معرض الصور"; 2 | "We require gallery permission to allow you to view and save photos. Tap the button below to get started" = "نحن بحاجة إلى إذن معرض الصور للسماح لك بعرض وحفظ الصور. اضغط على الزر أدناه للبدء."; 3 | "Grant Permissions" = "منح السماح"; 4 | 5 | // MARK: - Gallery Filter Overlay 6 | "Entire Library" = "المكتبة بأكملها"; 7 | "The default album which includes every photo in your library" = "الألبوم الافتراضي الذي يحتوي على كل صورة في مكتبتك."; 8 | 9 | "Selfies" = "السيلفي"; 10 | "An album that includes every photo taken with the front-facing camera" = "ألبوم يتضمن كل صورة تم التقاطها باستخدام الكاميرا الأمامية."; 11 | 12 | "Favourites" = "المفضلة"; 13 | "An album filled with your favourite photographs, as marked by you" = "ألبوم مليء بصورك المفضلة كما تم وضع علامة عليها من قبلك."; 14 | 15 | 16 | // MARK: - Screenshots Overlay 17 | "Hide Screenshots" = "إخفاء لقطات الشاشة"; 18 | "When viewing the entire album or your favourites, screenshots will be hidden" = "عند عرض الألبوم بأكمله أو المفضلة الخاصة بك، ستتم إخفاء لقطات الشاشة."; 19 | 20 | "Show Screenshots" = "عرض لقطات الشاشة"; 21 | "Screenshots will be visible in albums that include them" = "ستكون لقطات الشاشة مرئية في الألبومات التي تتضمنها."; 22 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/Resources/de.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Gallery Permissions" = "Galerie Berechtigungen"; 2 | "We require gallery permission to allow you to view and save photos. Tap the button below to get started" = "Wir benötigen die Berechtigung für die Galerie, um Ihnen das Anzeigen und Speichern von Fotos zu ermöglichen. Tippen Sie auf den Button unten, um zu beginnen"; 3 | "Grant Permissions" = "Berechtigungen erteilen"; 4 | 5 | // MARK: - Gallery Filter Overlay 6 | "Entire Library" = "Gesamte Bibliothek"; 7 | "The default album which includes every photo in your library" = "Das Standardalbum, das alle Fotos in Ihrer Bibliothek enthält"; 8 | 9 | "Selfies" = "Selfies"; 10 | "An album that includes every photo taken with the front-facing camera" = "Ein Album, das alle Fotos enthält, die mit der Frontkamera aufgenommen wurden"; 11 | 12 | "Favourites" = "Favourites"; 13 | "An album filled with your favourite photographs, as marked by you" = "Ein Album mit Ihren Lieblingsfotos, die von Ihnen markiert wurden"; 14 | 15 | 16 | // MARK: - Screenshots Overlay 17 | "Hide Screenshots" = "Bildschirmfotos ausblenden"; 18 | "When viewing the entire album or your favourites, screenshots will be hidden" = "Beim Anzeigen des gesamten Albums oder Ihrer Favoriten werden Screenshots ausgeblendet"; 19 | 20 | "Show Screenshots" = "Bildschirmfotos einblenden"; 21 | "Screenshots will be visible in albums that include them" = "Screenshots werden in Alben sichtbar sein, in denen welche enthalten sind"; 22 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Gallery Permissions" = "Gallery Permissions"; 2 | "We require gallery permission to allow you to view and save photos. Tap the button below to get started" = "We require gallery permission to allow you to view and save photos. Tap the button below to get started"; 3 | "Grant Permissions" = "Grant Permissions"; 4 | 5 | // MARK: - Gallery Filter Overlay 6 | "Entire Library" = "Entire Library"; 7 | "The default album which includes every photo in your library" = "The default album which includes every photo in your library"; 8 | 9 | "Selfies" = "Selfies"; 10 | "An album that includes every photo taken with the front-facing camera" = "An album that includes every photo taken with the front-facing camera"; 11 | 12 | "Favourites" = "Favourites"; 13 | "An album filled with your favourite photographs, as marked by you" = "An album filled with your favourite photographs, as marked by you"; 14 | 15 | 16 | // MARK: - Screenshots Overlay 17 | "Hide Screenshots" = "Hide Screenshots"; 18 | "When viewing the entire album or your favourites, screenshots will be hidden" = "When viewing the entire album or your favourites, screenshots will be hidden"; 19 | 20 | "Show Screenshots" = "Show Screenshots"; 21 | "Screenshots will be visible in albums that include them" = "Screenshots will be visible in albums that include them"; 22 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/Resources/es.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Gallery Permissions" = "Permisos para usar la galería"; 2 | "We require gallery permission to allow you to view and save photos. Tap the button below to get started" = "Se necesita acceso a la galería para ver y guardar fotos. Pulsa el botón de abajo para empezar"; 3 | "Grant Permissions" = "Otorgar permisos"; 4 | 5 | // MARK: - Gallery Filter Overlay 6 | "Entire Library" = "Biblioteca completa"; 7 | "The default album which includes every photo in your library" = "Álbum predeterminado que incluye todas las fotos de tu biblioteca"; 8 | 9 | "Selfies" = "Selfies"; 10 | "An album that includes every photo taken with the front-facing camera" = "Un álbum que incluye todas las fotos tomadas con la cámara frontal"; 11 | 12 | "Favourites" = "Favoritos"; 13 | "An album filled with your favourite photographs, as marked by you" = "Un álbum con tus fotografías favoritas, marcadas por ti"; 14 | 15 | 16 | // MARK: - Screenshots Overlay 17 | "Hide Screenshots" = "Esconder capturas de pantalla"; 18 | "When viewing the entire album or your favourites, screenshots will be hidden" = "Al visualizar el álbum completo o tus favoritos, las capturas de pantalla quedarán ocultas"; 19 | 20 | "Show Screenshots" = "Mostrar capturas de pantalla"; 21 | "Screenshots will be visible in albums that include them" = "Las capturas de pantalla serán visibles en los álbumes que las incluyan"; 22 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/Resources/hr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Gallery Permissions" = "Dozvole za galeriju"; 2 | "We require gallery permission to allow you to view and save photos. Tap the button below to get started" = "Potrebna nam je dozvola za galeriju da biste mogli da pregledate i sačuvate fotografije. Kliknite na dugme ispod da biste započeli"; 3 | "Grant Permissions" = "Daj Dozvole"; 4 | 5 | // MARK: - Gallery Filter Overlay 6 | "Entire Library" = "Cela biblioteka"; 7 | "The default album which includes every photo in your library" = "Podrazumevani album koji uključuje sve fotografije iz vaše biblioteke"; 8 | 9 | "Selfies" = "Selfiji"; 10 | "An album that includes every photo taken with the front-facing camera" = "Album koji uključuje sve fotografije snimljene prednjom kamerom"; 11 | 12 | "Favourites" = "Favoriti"; 13 | "An album filled with your favourite photographs, as marked by you" = "Album pun vaših omiljenih fotografija, kako ste ih obeležili"; 14 | 15 | // MARK: - Screenshots Overlay 16 | "Hide Screenshots" = "Sakrij Snimke ekrana"; 17 | "When viewing the entire album or your favourites, screenshots will be hidden" = "Kada gledate celi album ili vaše omiljene slike, snimci ekrana će biti sakriveni"; 18 | 19 | "Show Screenshots" = "Prikaži Snimke ekrana"; 20 | "Screenshots will be visible in albums that include them" = "Snimci ekrana će biti vidljivi u albumima koji ih imaju"; 21 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/Resources/ja.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Gallery Permissions" = "ギャラリーの許可"; 2 | "We require gallery permission to allow you to view and save photos. Tap the button below to get started" = "このアプリでは、特定の機能を有効にしたり、操作するために、ギャラリーへのアクセスを許可する必要があります。以下のボタンをタップしてください。"; 3 | "Grant Permissions" = "許可する"; 4 | 5 | 6 | // MARK: - Gallery Filter Overlay 7 | "Entire Library" = "ライブラリ全体"; 8 | "The default album which includes every photo in your library" = "ライブラリにあるすべての写真を含むデフォルトのアルバム"; 9 | 10 | "Selfies" = "セルフィー"; 11 | "An album that includes every photo taken with the front-facing camera" = "前面カメラで撮影したすべての写真を含むアルバム"; 12 | 13 | "Favourites" = "お気に入り"; 14 | "An album filled with your favourite photographs, as marked by you" = "あなたがお気に入りに入れた写真でいっぱいのアルバム"; 15 | 16 | 17 | // MARK: - Screenshots Overlay 18 | "Hide Screenshots" = "スクリーンショットを隠す"; 19 | "When viewing the entire album or your favourites, screenshots will be hidden" = "アルバム全体やお気に入りを表示している場合に、スクリーンショットが非表示になります"; 20 | 21 | "Show Screenshots" = "スクリーンショットを表示する"; 22 | "Screenshots will be visible in albums that include them" = "スクリーンショットが含まれるアルバムでは、スクリーンショットが表示されます"; 23 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/Resources/pl.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Gallery Permissions" = "Uprawnienia galerii"; 2 | "We require gallery permission to allow you to view and save photos. Tap the button below to get started" = "Wymagamy dostępu do galerii, aby umożliwić przeglądanie i zapisywanie zdjęć. Naciśnij przycisk poniżej, aby kontynuować"; 3 | "Grant Permissions" = "Zezwól"; 4 | 5 | // MARK: - Gallery Filter Overlay 6 | "Entire Library" = "Cała biblioteka"; 7 | "The default album which includes every photo in your library" = "Domyślny album zawierający wszystkie zdjęcia w bibliotece"; 8 | 9 | "Selfies" = "Selfie"; 10 | "An album that includes every photo taken with the front-facing camera" = "Album zawierający wszystkie zdjęcia wykonane przednim aparatem."; 11 | 12 | "Favourites" = "Ulubione"; 13 | "An album filled with your favourite photographs, as marked by you" = "Album wypełniony twoimi ulubionymi zdjęciami, oznaczonymi przez ciebie"; 14 | 15 | 16 | // MARK: - Screenshots Overlay 17 | "Hide Screenshots" = "Ukryj zrzuty ekranu"; 18 | "When viewing the entire album or your favourites, screenshots will be hidden" = "Podczas przeglądania całego albumu lub ulubionych zrzuty ekranu będą ukryte"; 19 | 20 | "Show Screenshots" = "Pokaż zrzuty ekranu"; 21 | "Screenshots will be visible in albums that include them" = "Zrzuty ekranu będą widoczne w albumach, które je zawierają"; 22 | -------------------------------------------------------------------------------- /GalleryFeature/Sources/GalleryFeature/Variables.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Photos 3 | import UIKit 4 | 5 | let imageManager: PHCachingImageManager = { 6 | let new = PHCachingImageManager() 7 | new.allowsCachingHighQualityImages = false 8 | return new 9 | }() 10 | 11 | let backgroundManager = PHCachingImageManager.default() 12 | var navigationController: UINavigationController? 13 | 14 | var assetsHolder: AssetsHolder! 15 | var bottomSafeArea: CGFloat { 16 | // #if !CAPTURE_EXTENSION 17 | // UIApplication.shared.windows.first?.rootViewController?.view.safeAreaInsets.bottom ?? 0 18 | // #else 19 | 0 20 | // #endif 21 | } 22 | var transitionController: AssetTransitionController? 23 | -------------------------------------------------------------------------------- /GalleryFeature/Tests/GalleryFeatureTests/GalleryFeatureTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import GalleryFeature 3 | 4 | final class GalleryFeatureTests: XCTestCase { } 5 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | 5 | plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') 6 | eval_gemfile(plugins_path) if File.exist?(plugins_path) 7 | -------------------------------------------------------------------------------- /Haptics/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | -------------------------------------------------------------------------------- /Haptics/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Haptics", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "Haptics", 14 | targets: ["Haptics"] 15 | ), 16 | ], 17 | dependencies: [ 18 | .package( 19 | name: "Shared", 20 | path: "../Shared" 21 | ), 22 | ], 23 | targets: [ 24 | .target( 25 | name: "Haptics", 26 | dependencies: [ 27 | .product( 28 | name: "Shared", 29 | package: "Shared" 30 | ) 31 | ], 32 | swiftSettings: [ 33 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 34 | ], 35 | linkerSettings: [ 36 | .unsafeFlags(["-Xlinker", "-application_extension"]) 37 | ] 38 | ), 39 | .testTarget( 40 | name: "HapticsTests", 41 | dependencies: ["Haptics"] 42 | ), 43 | ] 44 | ) 45 | -------------------------------------------------------------------------------- /Haptics/Tests/HapticsTests/HapticsTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Haptics 3 | 4 | final class HapticsTests: XCTestCase { } 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2025 EFF CORP. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /LocationClient/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /LocationClient/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "LocationClient", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "LocationClient", 14 | targets: ["LocationClient"] 15 | ), 16 | ], 17 | dependencies: [ 18 | .package(url: "https://github.com/AsyncSwift/AsyncLocationKit.git", .upToNextMinor(from: "1.6.1")), 19 | 20 | .package(name: "Preferences", path: "../Preferences"), 21 | .package(name: "Shared", path: "../Shared") 22 | ], 23 | targets: [ 24 | .target( 25 | name: "LocationClient", 26 | dependencies: [ 27 | .product(name: "AsyncLocationKit", package: "AsyncLocationKit"), 28 | 29 | .product(name: "Preferences", package: "Preferences"), 30 | .product(name: "Shared", package: "Shared"), 31 | ], 32 | swiftSettings: [ 33 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 34 | ], 35 | linkerSettings: [ 36 | .unsafeFlags(["-Xlinker", "-application_extension"]) 37 | ] 38 | ), 39 | .testTarget( 40 | name: "LocationClientTests", 41 | dependencies: ["LocationClient"] 42 | ), 43 | ] 44 | ) 45 | -------------------------------------------------------------------------------- /LocationClient/Tests/LocationClientTests/LocationClientTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import LocationClient 3 | 4 | final class LocationClientTests: XCTestCase { } 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PHONY: codegen 2 | codegen: ensure-sourcery-installed 3 | @./vendor/sourcery/bin/sourcery --config AVCaptureClient/Sources/AVCaptureClient/Sourcery.yml 4 | @./vendor/sourcery/bin/sourcery --config Pipeline/Sources/Pipeline/Sourcery.yml 5 | @./vendor/sourcery/bin/sourcery --config PermissionsClient/Sources/PermissionsClient/Sourcery.yml 6 | @./vendor/sourcery/bin/sourcery --config Preferences/Sources/Preferences/Sourcery.yml 7 | 8 | PHONY: ensure-sourcery-installed 9 | ensure-sourcery-installed: 10 | @sh ./Scripts/ensure-sourcery-installed.sh 11 | -------------------------------------------------------------------------------- /OrientationClient/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /OrientationClient/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "OrientationClient", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "OrientationClient", 14 | targets: ["OrientationClient"] 15 | ), 16 | ], 17 | dependencies: [ 18 | ], 19 | targets: [ 20 | .target( 21 | name: "OrientationClient", 22 | dependencies: [], 23 | swiftSettings: [ 24 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 25 | ], 26 | linkerSettings: [ 27 | .unsafeFlags(["-Xlinker", "-application_extension"]) 28 | ] 29 | ), 30 | .testTarget( 31 | name: "OrientationClientTests", 32 | dependencies: ["OrientationClient"] 33 | ), 34 | ] 35 | ) 36 | -------------------------------------------------------------------------------- /OrientationClient/Tests/OrientationClientTests/OrientationClientTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import OrientationClient 3 | 4 | final class OrientationClientTests: XCTestCase { } 5 | -------------------------------------------------------------------------------- /OverlayView/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /OverlayView/Tests/OverlayViewTests/OverlayViewTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import OverlayView 3 | 4 | final class OverlayViewTests: XCTestCase { 5 | func testExample() throws { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(OverlayView().text, "Hello, World!") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PermissionsClient/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /PermissionsClient/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "PermissionsClient", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "PermissionsClient", 14 | targets: ["PermissionsClient"] 15 | ), 16 | ], 17 | dependencies: [ 18 | .package(name: "Shared", path: "../Shared"), 19 | ], 20 | targets: [ 21 | .target( 22 | name: "PermissionsClient", 23 | dependencies: [ 24 | .product(name: "Shared", package: "Shared"), 25 | ], 26 | swiftSettings: [ 27 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 28 | ], 29 | linkerSettings: [ 30 | .unsafeFlags(["-Xlinker", "-application_extension"]) 31 | ] 32 | ), 33 | .testTarget( 34 | name: "PermissionsClientTests", 35 | dependencies: ["PermissionsClient"] 36 | ), 37 | ] 38 | ) 39 | -------------------------------------------------------------------------------- /PermissionsClient/Sources/PermissionsClient/Generated/AutoNullable.generated.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery 1.8.2 — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | // swiftlint:disable all 4 | 5 | import Foundation 6 | 7 | 8 | 9 | #if canImport(AVFoundation) 10 | import AVFoundation 11 | #endif 12 | 13 | #if canImport(Combine) 14 | import Combine 15 | #endif 16 | 17 | #if canImport(ComposableArchitecture) 18 | import ComposableArchitecture 19 | #endif 20 | 21 | #if canImport(CoreImage) 22 | import CoreImage 23 | #endif 24 | 25 | #if canImport(FoundationNetworking) 26 | import FoundationNetworking 27 | #endif 28 | 29 | #if canImport(UIKit) 30 | import UIKit 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /PermissionsClient/Sources/PermissionsClient/PermissionsClient.swift: -------------------------------------------------------------------------------- 1 | import Combine 2 | import ComposableArchitecture 3 | import Foundation 4 | import Shared 5 | 6 | @frozen 7 | public enum PermissionState { 8 | case undetermined, allowed, denied 9 | } 10 | 11 | public protocol PermissionsClient: AutoMockable { 12 | var checkCameraPermissions: PermissionState { get } 13 | var microphonePermissions: PermissionState { get } 14 | var requestCameraPermissions: EffectTask { get } 15 | var checkPhotoGalleryPermissions: PermissionState { get } 16 | var requestPhotoGalleryPermissions: EffectTask { get } 17 | var requestMicrophonePermissions: EffectTask { get } 18 | func registerForNotifications() 19 | func unregisterForNotifications() 20 | func openSystemSettings() 21 | } 22 | 23 | private enum PermissionsClientKey: DependencyKey { 24 | static let liveValue: PermissionsClient = LivePermissionsClient() 25 | static var testValue: PermissionsClient = PermissionsClientMock(override: true) 26 | } 27 | 28 | public extension DependencyValues { 29 | var permissionsClient: PermissionsClient { 30 | get { self[PermissionsClientKey.self] } 31 | set { self[PermissionsClientKey.self] = newValue } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /PermissionsClient/Sources/PermissionsClient/PermissionsClientMock.swift: -------------------------------------------------------------------------------- 1 | import AVFoundation 2 | import Combine 3 | import ComposableArchitecture 4 | import Foundation 5 | import Photos 6 | import UIKit 7 | 8 | extension PermissionsClientMock { 9 | public convenience init(override: Bool) { 10 | self.init() 11 | self.underlyingCheckPhotoGalleryPermissions = .undetermined 12 | self.underlyingCheckCameraPermissions = .undetermined 13 | self.underlyingRequestCameraPermissions = .fireAndForget { 14 | self.underlyingCheckCameraPermissions = .allowed 15 | } 16 | self.underlyingRequestPhotoGalleryPermissions = .fireAndForget { 17 | self.underlyingCheckPhotoGalleryPermissions = .allowed 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /PermissionsClient/Sources/PermissionsClient/Sourcery.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | - "." 3 | templates: 4 | - "../../../Shared/Sources/Shared/Sourcery/AutoMockable.stencil" 5 | - "../../../Shared/Sources/Shared/Sourcery/AutoNullable.stencil" 6 | output: 7 | "./Generated" 8 | -------------------------------------------------------------------------------- /PermissionsClient/Tests/PermissionsClientTests/PermissionsClientTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import PermissionsClient 3 | 4 | final class PermissionsClientTests: XCTestCase { 5 | func testExample() throws { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(PermissionsClient().text, "Hello, World!") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Pipeline/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Pipeline/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Pipeline", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "Pipeline", 14 | targets: ["Pipeline"] 15 | ), 16 | ], 17 | dependencies: [ 18 | /// Pipeline Target 19 | .package(name: "Core", path: "../Core"), 20 | .package(name: "Shared", path: "../Shared"), 21 | 22 | 23 | ], 24 | targets: [ 25 | .target( 26 | name: "Pipeline", 27 | dependencies: [ 28 | .product(name: "Core", package: "Core"), 29 | .product(name: "Shared", package: "Shared"), 30 | ], 31 | swiftSettings: [ 32 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 33 | ], 34 | linkerSettings: [ 35 | .unsafeFlags(["-Xlinker", "-application_extension"]) 36 | ] 37 | ), 38 | .testTarget( 39 | name: "PipelineTests", 40 | dependencies: [ 41 | "Pipeline", 42 | "Shared", 43 | ], 44 | resources: [ 45 | .process("Resources") 46 | ] 47 | ), 48 | ] 49 | ) 50 | -------------------------------------------------------------------------------- /Pipeline/Sources/Pipeline/Errors.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | enum Spectrum { 4 | case red, green, blue 5 | } 6 | 7 | public enum PipelineError: Error { 8 | case failedToGeneratePipeline 9 | case failedToBuildHistogram 10 | case failedToConvert 11 | case failedToGenerateImage 12 | case invalidState 13 | } 14 | -------------------------------------------------------------------------------- /Pipeline/Sources/Pipeline/Generated/AutoNullable.generated.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery 1.8.2 — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | // swiftlint:disable all 4 | 5 | import Foundation 6 | 7 | import Shared 8 | 9 | 10 | #if canImport(AVFoundation) 11 | import AVFoundation 12 | #endif 13 | 14 | #if canImport(Combine) 15 | import Combine 16 | #endif 17 | 18 | #if canImport(ComposableArchitecture) 19 | import ComposableArchitecture 20 | #endif 21 | 22 | #if canImport(CoreImage) 23 | import CoreImage 24 | #endif 25 | 26 | #if canImport(FoundationNetworking) 27 | import FoundationNetworking 28 | #endif 29 | 30 | #if canImport(UIKit) 31 | import UIKit 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /Pipeline/Sources/Pipeline/SoftwareNameEnricher.swift: -------------------------------------------------------------------------------- 1 | import AVFoundation 2 | import CoreImage 3 | import Foundation 4 | 5 | public class SoftwareNameEnricher: NSObject, AVCapturePhotoFileDataRepresentationCustomizer { 6 | public func replacementMetadata(for photo: AVCapturePhoto) -> [String: Any]? { 7 | var metadata = photo.metadata 8 | if var tiffDictionary = metadata[kCGImagePropertyTIFFDictionary as String] as? [String: Any] { 9 | tiffDictionary[kCGImagePropertyTIFFSoftware as String] = "Stops" 10 | metadata[kCGImagePropertyTIFFDictionary as String] = tiffDictionary 11 | } 12 | return metadata 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Pipeline/Sources/Pipeline/Sourcery.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | - "." 3 | templates: 4 | - "../../../Shared/Sources/Shared/Sourcery/AutoMockable.stencil" 5 | - "../../../Shared/Sources/Shared/Sourcery/AutoNullable.stencil" 6 | output: 7 | "./Generated" 8 | args: 9 | importShared: "true" 10 | -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/MonochromeTransformerTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | @testable import Pipeline 4 | 5 | final class MonochromeTransformerTests: XCTestCase { 6 | 7 | // MARK: - Properties 8 | private let context: CIContext = { 9 | if let device = MTLCreateSystemDefaultDevice() { 10 | return CIContext(mtlDevice: device) 11 | } else { 12 | return CIContext() 13 | } 14 | }() 15 | 16 | // MARK: - Tests 17 | 18 | func testDefaultConversion() throws { 19 | let url = Bundle.module.url(forResource: "portrait", withExtension: "jpg")! 20 | let portrait = CIImage(contentsOf: url)! 21 | 22 | let transformer = try Pipeline.MonochromeTransformer( 23 | image: portrait, 24 | context: context 25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/folia-high-contrast-and-warmth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/folia-high-contrast-and-warmth.png -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/folia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/folia.png -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/mononoke-front-v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/mononoke-front-v2.png -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/mononoke-front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/mononoke-front.png -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/mononoke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/mononoke.png -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/portrait.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/portrait.jpg -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/prt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/prt.png -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/still.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/still.tiff -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/supergold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/supergold.png -------------------------------------------------------------------------------- /Pipeline/Tests/PipelineTests/Resources/tx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Pipeline/Tests/PipelineTests/Resources/tx.png -------------------------------------------------------------------------------- /Preferences/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Preferences/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Preferences", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "Preferences", 14 | targets: ["Preferences"] 15 | ), 16 | ], 17 | dependencies: [ 18 | .package(name: "Shared", path: "../Shared"), 19 | ], 20 | targets: [ 21 | .target( 22 | name: "Preferences", 23 | dependencies: [ 24 | .product(name: "Shared", package: "Shared"), 25 | ], 26 | swiftSettings: [ 27 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 28 | ], 29 | linkerSettings: [ 30 | .unsafeFlags(["-Xlinker", "-application_extension"]) 31 | ] 32 | ), 33 | .testTarget( 34 | name: "PreferencesTests", 35 | dependencies: ["Preferences"] 36 | ), 37 | ] 38 | ) 39 | -------------------------------------------------------------------------------- /Preferences/Sources/Preferences/Generated/AutoNullable.generated.swift: -------------------------------------------------------------------------------- 1 | // Generated using Sourcery 1.8.2 — https://github.com/krzysztofzablocki/Sourcery 2 | // DO NOT EDIT 3 | // swiftlint:disable all 4 | 5 | import Foundation 6 | 7 | import Shared 8 | 9 | 10 | #if canImport(AVFoundation) 11 | import AVFoundation 12 | #endif 13 | 14 | #if canImport(Combine) 15 | import Combine 16 | #endif 17 | 18 | #if canImport(ComposableArchitecture) 19 | import ComposableArchitecture 20 | #endif 21 | 22 | #if canImport(CoreImage) 23 | import CoreImage 24 | #endif 25 | 26 | #if canImport(FoundationNetworking) 27 | import FoundationNetworking 28 | #endif 29 | 30 | #if canImport(UIKit) 31 | import UIKit 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /Preferences/Sources/Preferences/PreferencesClientMock.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Shared 3 | 4 | public extension PreferencesClientMock { 5 | convenience init(override: Bool) { 6 | self.init() 7 | underlyingPreferredAspectRatio = .fourByThree 8 | underlyingPreferredFlashMode = .on 9 | underlyingPreferredGalleryFilter = .all 10 | underlyingPreferredGrainPresence = GrainPresence.none 11 | underlyingPreferredShutterStyle = .dedicatedButton 12 | underlyingPreferredQuantization = .chromatic(.folia) 13 | underlyingShouldReverseCameraControls = false 14 | underlyingShouldEnableHaptics = true 15 | underlyingShouldIncludeScreenshotsInGallery = true 16 | underlyingPreferredLaunchDevicePosition = .front 17 | underlyingShouldAddCapturesToApplicationPhotoAlbum = true 18 | underlyingShouldEmbedLocationDataInCaptures = true 19 | underlyingShouldDoubleTapToFlipCamera = true 20 | underlyingShouldEnableSoundEffects = true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Preferences/Sources/Preferences/Sourcery.yml: -------------------------------------------------------------------------------- 1 | sources: 2 | - "." 3 | templates: 4 | - "../../../Shared/Sources/Shared/Sourcery/AutoMockable.stencil" 5 | - "../../../Shared/Sources/Shared/Sourcery/AutoNullable.stencil" 6 | output: 7 | "./Generated" 8 | args: 9 | importShared: "true" 10 | -------------------------------------------------------------------------------- /Preferences/Tests/PreferencesTests/PreferencesTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Preferences 3 | 4 | final class PreferencesTests: XCTestCase { 5 | func testExample() throws { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(Preferences().text, "Hello, World!") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Scripts/ensure-sourcery-installed.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | set -u 6 | 7 | required_version="$(cat .sourcery-version)" 8 | install_location=./vendor 9 | 10 | install() { 11 | if [ ! -d $install_location ]; then 12 | mkdir $install_location; 13 | fi; 14 | 15 | rm -f ./tmp/sourcery ./tmp/sourcery.zip 16 | rm -rf $install_location/sourcery 17 | 18 | curl --location --fail --retry 5 \ 19 | https://github.com/krzysztofzablocki/Sourcery/releases/download/"$required_version"/Sourcery-"$required_version".zip \ 20 | --output $install_location/sourcery.zip 21 | 22 | ( 23 | cd $install_location 24 | unzip -o sourcery.zip -d sourcery 25 | rm -rf sourcery.zip download 26 | echo "$required_version" > sourcery-version 27 | ) 28 | 29 | echo "Installed sourcery locally" 30 | } 31 | 32 | if [ ! -x $install_location/sourcery ]; then 33 | install 34 | elif [[ ! $required_version == $(cat $install_location/sourcery-version) ]]; then 35 | install 36 | fi 37 | -------------------------------------------------------------------------------- /Settings/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Settings/Sources/Settings/SettingsError.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum SettingsError: Error { 4 | case iconAlreadySet 5 | } 6 | -------------------------------------------------------------------------------- /Settings/Sources/Settings/SettingsIconView.swift: -------------------------------------------------------------------------------- 1 | import Aesthetics 2 | import ComposableArchitecture 3 | import Foundation 4 | import SwiftUI 5 | import Views 6 | 7 | public struct SettingsIconSelectionView: View { 8 | 9 | private var columns: Array { 10 | .init(repeating: .init(spacing: 10, alignment: .center), count: 4) 11 | } 12 | 13 | private let alternativeLightIcons: Array = AppIcon.lightIcons 14 | private let alternativeDarkIcons: Array = AppIcon.darkIcons 15 | 16 | private let store: StoreOf 17 | private let scheme: ColorScheme 18 | 19 | public init( 20 | store: StoreOf, 21 | scheme: ColorScheme 22 | ) { 23 | self.store = store 24 | self.scheme = scheme 25 | } 26 | 27 | public var body: some View { 28 | WithViewStore(store, observe: \.alternativeAppIconName) { appIconNameStore in 29 | LazyVGrid(columns: columns) { 30 | ForEach( 31 | scheme == .light ? alternativeLightIcons : alternativeDarkIcons 32 | ) { icon in 33 | Image(uiImage: icon.preview) 34 | .resizable() 35 | .aspectRatio(1, contentMode: .fill) 36 | .cornerRadius(17) 37 | .overlay(isShown: appIconNameStore.state == icon.iconName, alignment: .topTrailing) { 38 | SealCheckmark() 39 | .offset(x: 8.5, y: -8.5) 40 | } 41 | .onTapGesture { 42 | appIconNameStore.send(.didRequestSetAppIcon(icon)) 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Settings/Tests/SettingsTests/SettingsTests.swift: -------------------------------------------------------------------------------- 1 | import ComposableArchitecture 2 | import SnapshotTesting 3 | import XCTest 4 | 5 | @testable import Settings 6 | 7 | final class SettingsTests: XCTestCase { 8 | func testSettingsScreen() { 9 | let record = false 10 | let store = Store(initialState: .init(), reducer: SettingsFeature()) 11 | let view = SettingsView(store) 12 | .growToFitMainScreen() 13 | .environment(\.colorScheme, .dark) 14 | 15 | assertSnapshot(matching: view, as: .image, record: record) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Settings/Tests/SettingsTests/__Snapshots__/SettingsTests/testSettingsScreen.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Settings/Tests/SettingsTests/__Snapshots__/SettingsTests/testSettingsScreen.1.png -------------------------------------------------------------------------------- /Shared/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/AspectRatio.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum AspectRatio: String { 4 | case fiveByFour 5 | case fourByThree 6 | case threeByTwo 7 | case oneByOne 8 | 9 | public var landscape: CGSize { 10 | switch self { 11 | case .fiveByFour: return .init(width: 5, height: 4) 12 | case .fourByThree: return .init(width: 4, height: 3) 13 | case .threeByTwo: return .init(width: 3, height: 2) 14 | case .oneByOne: return .init(width: 1, height: 1) 15 | } 16 | } 17 | 18 | public var portrait: CGSize { 19 | switch self { 20 | case .fiveByFour: return .init(width: 4, height: 5) 21 | case .fourByThree: return .init(width: 3, height: 4) 22 | case .threeByTwo: return .init(width: 2, height: 3) 23 | case .oneByOne: return .init(width: 1, height: 1) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/Box.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | private final class Ref: Equatable { 4 | var val: T 5 | init(_ v: T) { 6 | self.val = v 7 | } 8 | 9 | static func == (lhs: Ref, rhs: Ref) -> Bool { 10 | lhs.val == rhs.val 11 | } 12 | } 13 | 14 | @propertyWrapper 15 | public struct Box: Equatable { 16 | private var ref: Ref 17 | 18 | public init(_ x: T) { 19 | self.ref = Ref(x) 20 | } 21 | 22 | public var wrappedValue: T { 23 | get { ref.val } 24 | set { 25 | if !isKnownUniquelyReferenced(&ref) { 26 | ref = Ref(newValue) 27 | return 28 | } 29 | ref.val = newValue 30 | } 31 | } 32 | 33 | public var projectedValue: Box { 34 | self 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/ChromaticTransformation.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum ChromaticTransformation: String, Equatable, CaseIterable { 4 | case folia 5 | case supergold 6 | case tonachrome 7 | } 8 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/Combine+ResultTask.swift: -------------------------------------------------------------------------------- 1 | import ComposableArchitecture 2 | import Foundation 3 | 4 | public extension Effect { 5 | static func resultTask( 6 | priority: TaskPriority? = nil, 7 | operation: @escaping @Sendable () async -> Result 8 | ) -> Self { 9 | Effect, Never> 10 | .task(priority: priority, operation: operation) 11 | .flatMap { result -> Self in 12 | switch result { 13 | case .success(let value): return Effect(value: value) 14 | case .failure(let error): return Effect(error: error) 15 | } 16 | } 17 | .eraseToEffect() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/CompositionBlendModes.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum CompositionBlendModes: String, CaseIterable { 4 | case CIAdditionCompositing 5 | case CIColorBlendMode 6 | case CIColorBurnBlendMode 7 | case CIColorDodgeBlendMode 8 | case CIDarkenBlendMode 9 | case CIDifferenceBlendMode 10 | case CIDivideBlendMode 11 | case CIExclusionBlendMode 12 | case CIHardLightBlendMode 13 | case CIHueBlendMode 14 | case CILightenBlendMode 15 | case CILinearBurnBlendMode 16 | case CILinearDodgeBlendMode 17 | case CILuminosityBlendMode 18 | case CIMaximumCompositing 19 | case CIMinimumCompositing 20 | case CIMultiplyBlendMode 21 | case CIMultiplyCompositing 22 | case CIOverlayBlendMode 23 | case CIPinLightBlendMode 24 | case CISaturationBlendMode 25 | case CIScreenBlendMode 26 | case CISoftLightBlendMode 27 | case CISourceAtopCompositing 28 | case CISourceInCompositing 29 | case CISourceOutCompositing 30 | case CISourceOverCompositing 31 | case CISubtractBlendMode 32 | } 33 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/ContrastPreset.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum ContrastPreset: String, Identifiable, CaseIterable { 4 | public var id: Self { self } 5 | 6 | case faded 7 | case neutral 8 | case punchy 9 | } 10 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/GalleryFilter.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum GalleryFilter: String { 4 | case all 5 | case favourites 6 | case selfies 7 | } 8 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/GrainPresence.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum GrainPresence: String, CaseIterable { 4 | case none 5 | case normal 6 | case high 7 | } 8 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/Locales.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Locale { 4 | static var arabic: Locale = .init(identifier: "ar_EG") 5 | static var croatian: Locale = .init(identifier: "hr_HR") 6 | static var french: Locale = .init(identifier: "fr_FR") 7 | static var german: Locale = .init(identifier: "de_DE") 8 | static var japanese: Locale = .init(identifier: "ja_JP") 9 | static var polish: Locale = .init(identifier: "pl_PL") 10 | static var spanish: Locale = .init(identifier: "es_") 11 | } 12 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/Screen.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum Screen: Equatable { 4 | case camera 5 | case shoebox 6 | } 7 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/Sequence+Keypaths.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Sequence { 4 | func sorted(by keyPath: KeyPath) -> [Element] { 5 | return sorted { a, b in 6 | return a[keyPath: keyPath] < b[keyPath: keyPath] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/ShutterStyle.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public enum ShutterStyle: String, Equatable { 5 | case dedicatedButton 6 | case viewfinder 7 | 8 | public var bottomBarHeight: CGFloat { 9 | switch self { 10 | case .dedicatedButton: return 75 11 | case .viewfinder: return 60 12 | } 13 | } 14 | 15 | public var bottomBarTransitionOffset: CGFloat { 16 | switch self { 17 | case .dedicatedButton: return 73 18 | case .viewfinder: return 73 19 | } 20 | } 21 | } 22 | 23 | private struct ShutterStyleKey: EnvironmentKey { 24 | static public let defaultValue = ShutterStyle.dedicatedButton 25 | } 26 | 27 | public extension EnvironmentValues { 28 | var shutterStyle: ShutterStyle { 29 | get { self[ShutterStyleKey.self] } 30 | set { self[ShutterStyleKey.self] = newValue } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/Sourcery/SourceryProtocols.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public protocol AutoNullable {} 4 | public protocol AutoMockable {} 5 | public protocol AutomaticSettings: Codable, Equatable {} 6 | public protocol AutomaticSettingsEnum: RawRepresentable, Codable, Equatable, CaseIterable {} 7 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/TCA+OptionalCache.swift: -------------------------------------------------------------------------------- 1 | import ComposableArchitecture 2 | import Foundation 3 | 4 | /// Creates a memoized cache that always returns the last non-`nil` value. 5 | /// 6 | /// Useful for preserving a presented UI during the programmatic dismissal of sheets and other forms 7 | /// of navigation, where setting state to `nil` drives dismissal. 8 | public func returningLastNonNilValue(_ f: @escaping (A) -> B?) -> (A) -> B? { 9 | var lastWrapped: B? 10 | return { wrapped in 11 | lastWrapped = f(wrapped) ?? lastWrapped 12 | return lastWrapped 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/TemperaturePreset.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum TemperaturePreset: String, Identifiable, CaseIterable { 4 | public var id: Self { self } 5 | 6 | case cool 7 | case neutral 8 | case warm 9 | } 10 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/View+ExtendFrame.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public extension View { 4 | func frame(dimension: CGFloat?, alignment: Alignment = .center) -> some View { 5 | frame(width: dimension, height: dimension, alignment: alignment) 6 | } 7 | 8 | func frame(size: CGSize) -> some View { 9 | frame(width: size.width, height: size.height) 10 | } 11 | 12 | func extendFrame(_ axes: Axis.Set = [.horizontal, .vertical], alignment: Alignment = .center) -> some View { 13 | frame( 14 | maxWidth: axes.contains(.horizontal) ? .infinity : nil, 15 | maxHeight: axes.contains(.vertical) ? .infinity : nil, 16 | alignment: alignment 17 | ) 18 | } 19 | 20 | #if canImport(UIKit) 21 | func growToFitMainScreen(_ axes: Axis.Set = [.horizontal, .vertical], alignment: Alignment = .center) -> some View { 22 | frame( 23 | width: axes.contains(.horizontal) ? UIScreen.main.bounds.size.width : nil, 24 | height: axes.contains(.vertical) ? UIScreen.main.bounds.size.height : nil, 25 | alignment: alignment 26 | ) 27 | } 28 | #endif 29 | } 30 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/View+OnSizeChange.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | fileprivate struct SizeKey: PreferenceKey { 4 | static var defaultValue: CGSize { .zero } 5 | 6 | static func reduce(value: inout CGSize, nextValue: () -> CGSize) { 7 | value = nextValue() 8 | } 9 | } 10 | 11 | public extension View { 12 | func onSizeChange(_ onChange: @escaping @MainActor (CGSize) -> ()) -> some View { 13 | overlay { 14 | GeometryReader { proxy in 15 | Color.clear.preference(key: SizeKey.self, value: proxy.size) 16 | } 17 | .onPreferenceChange( 18 | SizeKey.self, 19 | perform: { key in 20 | DispatchQueue.main.async { 21 | onChange(key) 22 | } 23 | } 24 | ) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/View+Overlay.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public extension View { 4 | func overlay( 5 | isShown: Bool, 6 | _ style: S, 7 | ignoresSafeAreaEdges edges: Edge.Set = .all 8 | ) -> some View { 9 | return overlay { 10 | if isShown { 11 | Color.clear.edgesIgnoringSafeArea(edges).overlay(style) 12 | } 13 | } 14 | } 15 | 16 | func overlay( 17 | isShown: Bool, 18 | alignment: Alignment = .center, 19 | @ViewBuilder _ content: @escaping () -> Content 20 | ) -> some View { 21 | overlay(alignment: alignment) { 22 | if isShown { 23 | content() 24 | } 25 | } 26 | } 27 | 28 | func overlay( 29 | item: Item?, 30 | alignment: Alignment = .center, 31 | @ViewBuilder _ content: @escaping (Item) -> Content 32 | ) -> some View { 33 | overlay(alignment: alignment) { 34 | item.map(content) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Shared/Sources/Shared/WarholTransformation.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum WarholTransformation: String, Equatable, CaseIterable { 4 | case bubblegum 5 | case darkroom 6 | case glowInTheDark 7 | case habenero 8 | } 9 | -------------------------------------------------------------------------------- /Shared/Tests/SharedTests/SharedTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Shared 3 | 4 | final class SharedTests: XCTestCase { 5 | func testExample() throws { } 6 | } 7 | -------------------------------------------------------------------------------- /Shoebox/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Shoebox/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Shoebox", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "Shoebox", 14 | targets: ["Shoebox"] 15 | ), 16 | ], 17 | dependencies: [ 18 | .package(name: "Shared", path: "../Shared"), 19 | ], 20 | targets: [ 21 | .target( 22 | name: "Shoebox", 23 | dependencies: [ 24 | .product(name: "Shared", package: "Shared"), 25 | ], 26 | swiftSettings: [ 27 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 28 | ], 29 | linkerSettings: [ 30 | .unsafeFlags(["-Xlinker", "-application_extension"]) 31 | ] 32 | ), 33 | .testTarget( 34 | name: "ShoeboxTests", 35 | dependencies: ["Shoebox"] 36 | ), 37 | ] 38 | ) 39 | -------------------------------------------------------------------------------- /Shoebox/Tests/ShoeboxTests/ShoeboxTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Shoebox 3 | 4 | final class ShoeboxTests: XCTestCase { 5 | func testExample() throws { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(Shoebox().text, "Hello, World!") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Shopfront/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Shopfront/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Shopfront", 7 | defaultLocalization: "en", 8 | platforms: [ 9 | .iOS(.v16), 10 | .macOS(.v12), 11 | ], 12 | products: [ 13 | .library( 14 | name: "Shopfront", 15 | targets: ["Shopfront"] 16 | ), 17 | ], 18 | dependencies: [ 19 | .package(path: "../Aesthetics"), 20 | .package(path: "../OverlayView"), 21 | .package(path: "../Shared"), 22 | .package(path: "../Views"), 23 | 24 | .package(url: "https://github.com/efremidze/Shiny", branch: "master") 25 | ], 26 | targets: [ 27 | .target( 28 | name: "Shopfront", 29 | dependencies: [ 30 | .product(name: "Aesthetics", package: "Aesthetics"), 31 | .product(name: "OverlayView", package: "OverlayView"), 32 | .product(name: "Shared", package: "Shared"), 33 | .product(name: "Views", package: "Views"), 34 | 35 | .product(name: "Shiny", package: "Shiny"), 36 | ], 37 | resources: [ 38 | .process("Resources") 39 | ], 40 | swiftSettings: [ 41 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 42 | ], 43 | linkerSettings: [ 44 | .unsafeFlags(["-Xlinker", "-application_extension"]) 45 | ] 46 | ), 47 | .testTarget( 48 | name: "ShopfrontTests", 49 | dependencies: ["Shopfront"] 50 | ), 51 | ] 52 | ) 53 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Benefits.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum ProBenefits: String, CaseIterable { 4 | case colourProfiles 5 | case customAppIcons 6 | } 7 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Errors.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public enum ShopfrontError: Error { 4 | case failedToFetchProduct 5 | } 6 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Identifiers.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import StoreKit 3 | 4 | extension Product { 5 | public struct Pro { 6 | public static let monthly = "com.eff.corp.aperture.pro.onemonthly" 7 | public static let yearly = "com.eff.corp.aperture.pro.oneyearly" 8 | } 9 | 10 | static let identifiers: [String] = [ 11 | Product.Pro.monthly, 12 | Product.Pro.yearly 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Resources/ar.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "perMonth" = "/بالشهر"; 2 | "perYear" = "/بالسنة"; 3 | 4 | "Best Value" = "أفضل قيمة"; 5 | "Most Popular" = "الاكثر شهرة"; 6 | "Fun!" = "مرح!"; 7 | 8 | "Quantization Algorithms" = "خوارزميات التجانس"; 9 | "Custom App Icons" = "أيقونات التطبيق المخصصة"; 10 | 11 | "Continue" = "متابعة"; 12 | 13 | "12 Months" = "١٢ شهرًا"; 14 | "1 Month" = "شهر واحد"; 15 | 16 | "Annually" = "سنويًا"; 17 | "Monthly" = "شهريًا"; 18 | 19 | "Savings" = "الوفورات"; 20 | 21 | "Folia" = "فوليا"; 22 | "Supergold" = "سوبرجولد"; 23 | "Monochrome" = "أحادي اللون"; 24 | "Quirky" = "منعشة"; 25 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Resources/de.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "perMonth" = "/Monat"; 2 | "perYear" = "/Jahr"; 3 | 4 | "Best Value" = "Bestes Preis-Leistungs-Verhältnis"; 5 | "Most Popular" = "Am beliebtesten"; 6 | "Fun!" = "Spaß!"; 7 | 8 | "Quantization Algorithms" = "Quantisierungsalgorithmen"; 9 | "Custom App Icons" = "Benutzerdefinierte App-Icons"; 10 | 11 | "Continue" = "Fortfahren"; 12 | 13 | "12 Months" = "12 Monate"; 14 | "1 Month" = "1 Monat"; 15 | 16 | "Annually" = "Jährlich"; 17 | "Monthly" = "Monatlich"; 18 | 19 | "Savings" = "Ersparnis"; 20 | 21 | "Folia" = "Folia"; 22 | "Supergold" = "Supergold"; 23 | "Monochrome" = "Monochrome"; 24 | "Quirky" = "Quirky"; 25 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "perMonth" = "/mo"; 2 | "perYear" = "/year"; 3 | 4 | "Best Value" = "Best Value"; 5 | "Most Popular" = "Most Popular"; 6 | "Fun!" = "Fun!"; 7 | 8 | "Quantization Algorithms" = "Quantization Algorithms"; 9 | "Custom App Icons" = "Custom App Icons"; 10 | 11 | "Continue" = "Continue"; 12 | 13 | "12 Months" = "12 Months"; 14 | "1 Month" = "1 Month"; 15 | 16 | "Annually" = "annually"; 17 | "Monthly" = "monthly"; 18 | 19 | "Savings" = "savings"; 20 | 21 | "Folia" = "Folia"; 22 | "Supergold" = "Supergold"; 23 | "Monochrome" = "Monochrome"; 24 | "Quirky" = "Quirky"; 25 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Resources/es.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "perMonth" = "/mensual"; 2 | "perYear" = "/anual"; 3 | 4 | "Best Value" = "Mejor precio"; 5 | "Most Popular" = "Más popular"; 6 | "Fun!" = "¡Divertido!"; 7 | 8 | "Quantization Algorithms" = "Algoritmos de cuantificación"; 9 | "Custom App Icons" = "Iconos personalizados"; 10 | 11 | "Continue" = "Continuar"; 12 | 13 | "12 Months" = "12 Meses"; 14 | "1 Month" = "1 Mes"; 15 | 16 | "Annually" = "Anual"; 17 | "Monthly" = "Mensual"; 18 | 19 | "Savings" = "Ahorro"; 20 | 21 | "Folia" = "Folia"; 22 | "Supergold" = "Súper oro"; 23 | "Monochrome" = "Monocromatico"; 24 | "Quirky" = "Extravagante"; 25 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Resources/fr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "perMonth" = "/mois"; 2 | "perYear" = "/an"; 3 | 4 | "Best Value" = "Meilleure offre"; 5 | "Most Popular" = "Le plus populaire"; 6 | "Fun!" = "Fun!"; 7 | 8 | "Quantization Algorithms" = "Algorithmes de quantification"; 9 | "Custom App Icons" = "Icônes d'app personnalisées"; 10 | 11 | "Continue" = "Continuer"; 12 | 13 | "12 Months" = "12 mois"; 14 | "1 Month" = "1 mois"; 15 | 16 | "Annually" = "annuellement"; 17 | "Monthly" = "mensuellement"; 18 | 19 | "Savings" = "économies"; 20 | 21 | "Folia" = "Folia"; 22 | "Supergold" = "Supergold"; 23 | "Monochrome" = "Monochrome"; 24 | "Quirky" = "Décalé"; 25 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Resources/hr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "perMonth" = "/mes"; 2 | "perYear" = "/god"; 3 | 4 | "Best Value" = "Najbolja vrednost"; 5 | "Most Popular" = "Najpopularnije"; 6 | "Fun!" = "Zabavno!"; 7 | 8 | "Quantization Algorithms" = "Algoritmi za kvantizaciju"; 9 | "Custom App Icons" = "Druge ikone aplikacije"; 10 | 11 | "Continue" = "Nastavi"; 12 | 13 | "12 Months" = "12 meseci"; 14 | "1 Month" = "1 mesec"; 15 | 16 | "Annually" = "godišnje"; 17 | "Monthly" = "mesečno"; 18 | 19 | "Savings" = "uštede"; 20 | 21 | "Folia" = "Folia"; 22 | "Supergold" = "Supergold"; 23 | "Monochrome" = "Monohromatski"; 24 | "Quirky" = "Čudno"; 25 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Resources/ja.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "perMonth" = "/月"; 2 | "perYear" = "/年"; 3 | 4 | "/mo" = "/月"; 5 | "/year" = "/年"; 6 | 7 | "Best Value" = "お得"; 8 | "Most Popular" = "一番人気"; 9 | "Fun!" = "楽しい!"; 10 | 11 | "Quantization Algorithms" = "より多くのカラープロファイル"; 12 | "Custom App Icons" = "アプリアイコンのカスタマイズ"; 13 | 14 | "Continue" = "続行"; 15 | 16 | "Annually" = "年額"; 17 | "Monthly" = "月額"; 18 | 19 | "12 Months" = "12 ヶ月"; 20 | "1 Month" = "1 ヶ月"; 21 | 22 | "Savings" = "お得"; 23 | 24 | "Folia" = "フォリア"; 25 | "Supergold" = "スーパーゴールド"; 26 | "Monochrome" = "モノクロ"; 27 | "Quirky" = "ロモグラフィー"; 28 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Resources/pl.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "perMonth" = "/mies."; 2 | "perYear" = "/rok"; 3 | 4 | "Best Value" = "Najlepsza opcja"; 5 | "Most Popular" = "Najpopularniejsza"; 6 | "Fun!" = "Pobaw się!"; 7 | 8 | "Quantization Algorithms" = "Algorytmy kwantyzacji"; 9 | "Custom App Icons" = "Dodatkowe ikony aplikacji"; 10 | 11 | "Continue" = "Kontynuuj"; 12 | 13 | "12 Months" = "12 miesięcy"; 14 | "1 Month" = "1 miesiąc"; 15 | 16 | "Annually" = "rocznie"; 17 | "Monthly" = "miesięcznie"; 18 | 19 | "Savings" = "oszczędność"; 20 | 21 | "Folia" = "Folia"; 22 | "Supergold" = "Supergold"; 23 | "Monochrome" = "Monochrom"; 24 | "Quirky" = "Dziwaczny"; 25 | -------------------------------------------------------------------------------- /Shopfront/Sources/Shopfront/Shopfront+Environment.swift: -------------------------------------------------------------------------------- 1 | import ComposableArchitecture 2 | import Foundation 3 | 4 | private enum ShopfrontClientKey: DependencyKey { 5 | static let liveValue: ShopfrontClient = ShopfrontClient.shared 6 | static var testValue: ShopfrontClient = ShopfrontClient.shared 7 | } 8 | 9 | public extension DependencyValues { 10 | var shopfrontClient: ShopfrontClient { 11 | get { self[ShopfrontClientKey.self] } 12 | set { self[ShopfrontClientKey.self] = newValue } 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /Shopfront/Tests/ShopfrontTests/ShopfrontTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Shopfront 3 | 4 | final class ShopfrontTests: XCTestCase { } 5 | -------------------------------------------------------------------------------- /Stops.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Stops.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Stops.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Stops/App.swift: -------------------------------------------------------------------------------- 1 | import ComposableArchitecture 2 | import Sentry 3 | import SwiftUI 4 | 5 | @main 6 | struct apertureApp: App { 7 | 8 | @UIApplicationDelegateAdaptor 9 | private var delegate: AppDelegate 10 | private let store = Store(initialState: AppFeature.State(), reducer: AppFeature()) 11 | 12 | var body: some Scene { 13 | WindowGroup { 14 | AppView(store) 15 | .preferredColorScheme(.dark) 16 | .edgesIgnoringSafeArea(.all) 17 | .registerCustomFonts() 18 | } 19 | } 20 | 21 | public init() { 22 | #if !DEBUG 23 | SentrySDK.start { options in 24 | options.dsn = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 25 | options.tracesSampleRate = 1.0 26 | options.enableAppHangTracking = false 27 | } 28 | #endif 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Stops/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Shopfront 3 | import StoreKit 4 | import UIKit 5 | 6 | final class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject { 7 | 8 | func application( 9 | _ application: UIApplication, 10 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil 11 | ) -> Bool { 12 | SKPaymentQueue.default().add(ShopfrontClient.shared) 13 | return true 14 | } 15 | 16 | func applicationWillTerminate( 17 | _ application: UIApplication 18 | ) { 19 | SKPaymentQueue.default().remove(ShopfrontClient.shared) 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Stops/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ITSAppUsesNonExemptEncryption 6 | 7 | UIViewControllerBasedStatusBarAppearance 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Stops/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIcon.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIcon.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeige.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeige.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeige.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeigeNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeigeNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBeigeNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlue.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlue.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlue.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlueNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlueNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconBlueNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellow.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellow.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellow.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellowNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellowNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Dark Icons/DarkAppIconYellowNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconBeige.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconBeige.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Light Icons/AppIconBeige.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconBeigeNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconBeigeNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Light Icons/AppIconBeigeNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconBlue.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconBlue.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Light Icons/AppIconBlue.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconBlueNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconBlueNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Light Icons/AppIconBlueNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Light Icons/AppIconNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconPrimaryHighResolutionPreview.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconPrimaryHighResolutionPreview.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Light Icons/AppIconPrimaryHighResolutionPreview.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconYellow.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconYellow.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Light Icons/AppIconYellow.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconYellowNoBlob.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-1024x1024.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/AppIconYellowNoBlob.appiconset/Icon-App-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/Light Icons/AppIconYellowNoBlob.appiconset/Icon-App-1024x1024.png -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/Light Icons/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/squarebuttonshadow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "squarebuttonshadow.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Stops/Resources/Assets.xcassets/squarebuttonshadow.imageset/squarebuttonshadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/Stops/Resources/Assets.xcassets/squarebuttonshadow.imageset/squarebuttonshadow.png -------------------------------------------------------------------------------- /Stops/Resources/ar.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Stops" = "Stops"; 2 | -------------------------------------------------------------------------------- /Stops/Resources/de.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Stops" = "Stops"; 2 | -------------------------------------------------------------------------------- /Stops/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Stops" = "Stops"; 2 | -------------------------------------------------------------------------------- /Stops/Resources/es.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Stops" = "Stops"; 2 | -------------------------------------------------------------------------------- /Stops/Resources/fr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Stops" = "Stops"; 2 | -------------------------------------------------------------------------------- /Stops/Resources/hr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Stops" = "Stops"; 2 | -------------------------------------------------------------------------------- /Stops/Resources/ja.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Stops" = "ストップ"; 2 | -------------------------------------------------------------------------------- /Stops/Resources/pl.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | "Stops" = "Stops"; 2 | -------------------------------------------------------------------------------- /Stops/aperture.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /StopsTests/__Snapshots__/apertureTests/testScreens.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/StopsTests/__Snapshots__/apertureTests/testScreens.1.png -------------------------------------------------------------------------------- /StopsTests/apertureTests.swift: -------------------------------------------------------------------------------- 1 | import AVCaptureClient 2 | import CoreImage 3 | import ComposableArchitecture 4 | import SnapshotTesting 5 | import XCTest 6 | 7 | @testable import Stops 8 | 9 | final class apertureTests: XCTestCase { } 10 | -------------------------------------------------------------------------------- /Views/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /Views/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Views", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "Views", 14 | targets: ["Views"] 15 | ), 16 | ], 17 | dependencies: [ 18 | .package(url: "https://github.com/stokatyan/ScrollCounter", branch: "master"), 19 | 20 | .package(name: "Aesthetics", path: "../Aesthetics"), 21 | .package(name: "Preferences", path: "../Preferences"), 22 | ], 23 | targets: [ 24 | .target( 25 | name: "Views", 26 | dependencies: [ 27 | .product(name: "ScrollCounter", package: "ScrollCounter"), 28 | 29 | .product(name: "Aesthetics", package: "Aesthetics"), 30 | .product(name: "Preferences", package: "Preferences"), 31 | ], 32 | swiftSettings: [ 33 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 34 | ], 35 | linkerSettings: [ 36 | .unsafeFlags(["-Xlinker", "-application_extension"]) 37 | ] 38 | ), 39 | .testTarget( 40 | name: "ViewsTests", 41 | dependencies: ["Views"] 42 | ), 43 | ] 44 | ) 45 | -------------------------------------------------------------------------------- /Views/Sources/Views/EmbossedText.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public struct EmbossedText: View { 5 | 6 | private let text: String 7 | 8 | public init(_ text: String) { self.text = text } 9 | 10 | public var body: some View { 11 | ZStack { 12 | Text(text) 13 | .foregroundColor(.white) 14 | .offset(y: 1) 15 | 16 | Text(text) 17 | .foregroundColor(.black) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Views/Sources/Views/LockedCameraUtils.swift: -------------------------------------------------------------------------------- 1 | import AVKit 2 | import Foundation 3 | import SwiftUI 4 | 5 | @available(iOS 17.2, *) 6 | private struct CaptureInteractionView: UIViewRepresentable { 7 | var action: () -> Void 8 | 9 | func makeUIView(context: Context) -> some UIView { 10 | let uiView = UIView() 11 | let interaction = AVCaptureEventInteraction { event in 12 | if event.phase == .began { action() } 13 | } 14 | uiView.addInteraction(interaction) 15 | return uiView 16 | } 17 | 18 | func updateUIView(_ uiView: UIViewType, context: Context) { } 19 | } 20 | 21 | public extension View { 22 | @ViewBuilder 23 | func onPressCapture( 24 | action: @escaping () -> Void 25 | ) -> some View { 26 | if #available(iOS 17.2, *) { 27 | self.background { 28 | CaptureInteractionView(action: action) 29 | } 30 | } else { 31 | self 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Views/Sources/Views/SealCheckmark.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | public struct SealCheckmark: View { 4 | public var body: some View { 5 | ZStack { 6 | Image(systemName: "seal.fill") 7 | .resizable() 8 | .frame(dimension: 25) 9 | .foregroundColor(.green) 10 | .blendMode(.difference) 11 | 12 | Image(systemName: "checkmark") 13 | .resizable() 14 | .font(Font.title.weight(.black)) 15 | .frame(dimension: 10) 16 | } 17 | } 18 | 19 | public init() { } 20 | } 21 | -------------------------------------------------------------------------------- /Views/Sources/Views/ShareSheet.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | 4 | public struct ShareSheet: UIViewControllerRepresentable { 5 | let activityItems: [Any] 6 | let completionHandler: (Bool) -> () 7 | 8 | public init( 9 | activityItems: [Any], 10 | completionHandler: @escaping (Bool) -> () 11 | ) { 12 | self.activityItems = activityItems 13 | self.completionHandler = completionHandler 14 | } 15 | 16 | public func makeUIViewController(context: Context) -> UIActivityViewController { 17 | let viewController = UIActivityViewController( 18 | activityItems: activityItems, 19 | applicationActivities: nil 20 | ) 21 | viewController.completionWithItemsHandler = { _, didComplete, _, _ in 22 | completionHandler(didComplete) 23 | } 24 | return viewController 25 | } 26 | 27 | public func updateUIViewController( 28 | _ uiViewController: UIActivityViewController, 29 | context: Context 30 | ) { } 31 | } 32 | -------------------------------------------------------------------------------- /Views/Tests/ViewsTests/ViewsTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Views 3 | 4 | final class ViewsTests: XCTestCase { 5 | func testExample() throws { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(Views().text, "Hello, World!") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /VolumeButtonInteractor/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/config/registries.json 8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 9 | .netrc 10 | -------------------------------------------------------------------------------- /VolumeButtonInteractor/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "VolumeButtonInteractor", 7 | platforms: [ 8 | .iOS(.v16), 9 | .macOS(.v12), 10 | ], 11 | products: [ 12 | .library( 13 | name: "VolumeButtonInteractor", 14 | targets: ["VolumeButtonInteractor"] 15 | ), 16 | ], 17 | dependencies: [ 18 | ], 19 | targets: [ 20 | .target( 21 | name: "VolumeButtonInteractor", 22 | dependencies: [], 23 | swiftSettings: [ 24 | .unsafeFlags(["-Xfrontend", "-application-extension"]) 25 | ], 26 | linkerSettings: [ 27 | .unsafeFlags(["-Xlinker", "-application_extension"]) 28 | ] 29 | ), 30 | .testTarget( 31 | name: "VolumeButtonInteractorTests", 32 | dependencies: ["VolumeButtonInteractor"] 33 | ), 34 | ] 35 | ) 36 | -------------------------------------------------------------------------------- /VolumeButtonInteractor/Sources/VolumeButtonInteractor/Log.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import os.log 3 | 4 | extension OSLog { 5 | private static let subsystem = "com.eff.corp.aperture.VolumeButtonHandler" 6 | private static let category = "audio_session" 7 | static let audioSession = OSLog(subsystem: OSLog.subsystem, category: OSLog.category) 8 | } 9 | 10 | func logEvent(_ message: String, _ category: OSLog) { 11 | os_log("%{public}@", log: category, type: .info, message) 12 | } 13 | -------------------------------------------------------------------------------- /VolumeButtonInteractor/Tests/VolumeButtonInteractorTests/VolumeButtonInteractorTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import VolumeButtonInteractor 3 | 4 | final class VolumeButtonInteractorTests: XCTestCase { 5 | func testExample() throws { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | XCTAssertEqual(VolumeButtonInteractor().text, "Hello, World!") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /aperture.app.dSYM.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rehatkathuria/stops/cd9d853f054558bb71e4791a96f7f115ccf049a1/aperture.app.dSYM.zip -------------------------------------------------------------------------------- /fastlane/Appfile: -------------------------------------------------------------------------------- 1 | app_identifier("com.eff.corp.aperture") # The bundle identifier of your app 2 | apple_id("crabapple@eff.co") # Your Apple Developer Portal username 3 | 4 | itc_team_id("125942868") # App Store Connect Team ID 5 | team_id("TAG9VCMY36") # Developer Portal Team ID 6 | 7 | # For more information about the Appfile, see: 8 | # https://docs.fastlane.tools/advanced/#appfile 9 | -------------------------------------------------------------------------------- /fastlane/Pluginfile: -------------------------------------------------------------------------------- 1 | # Autogenerated by fastlane 2 | # 3 | # Ensure this file is checked in to source control! 4 | 5 | gem 'fastlane-plugin-sentry' 6 | -------------------------------------------------------------------------------- /fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ---- 3 | 4 | # Installation 5 | 6 | Make sure you have the latest version of the Xcode command line tools installed: 7 | 8 | ```sh 9 | xcode-select --install 10 | ``` 11 | 12 | For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) 13 | 14 | # Available Actions 15 | 16 | ## iOS 17 | 18 | ### ios beta 19 | 20 | ```sh 21 | [bundle exec] fastlane ios beta 22 | ``` 23 | 24 | Push a new beta build to TestFlight 25 | 26 | ### ios load_key 27 | 28 | ```sh 29 | [bundle exec] fastlane ios load_key 30 | ``` 31 | 32 | 33 | 34 | ### ios signing 35 | 36 | ```sh 37 | [bundle exec] fastlane ios signing 38 | ``` 39 | 40 | 41 | 42 | ### ios build 43 | 44 | ```sh 45 | [bundle exec] fastlane ios build 46 | ``` 47 | 48 | 49 | 50 | ### ios prerelease_tests 51 | 52 | ```sh 53 | [bundle exec] fastlane ios prerelease_tests 54 | ``` 55 | 56 | 57 | 58 | ### ios dsym 59 | 60 | ```sh 61 | [bundle exec] fastlane ios dsym 62 | ``` 63 | 64 | 65 | 66 | ### ios upload 67 | 68 | ```sh 69 | [bundle exec] fastlane ios upload 70 | ``` 71 | 72 | 73 | 74 | ---- 75 | 76 | This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. 77 | 78 | More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). 79 | 80 | The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 81 | -------------------------------------------------------------------------------- /swiftgen.yml: -------------------------------------------------------------------------------- 1 | input_dir: ./ 2 | output_dir: ./ 3 | 4 | fonts: 5 | inputs: Aesthetics/Sources/Aesthetics/Resources 6 | outputs: 7 | templateName: swift5 8 | params: 9 | forceProvidesNamespaces: true 10 | publicAccess: true 11 | output: Aesthetics/Sources/Aesthetics/Fonts+Typesafe.swift 12 | 13 | xcassets: 14 | inputs: 15 | - Aesthetics/Sources/Aesthetics/Resources/Assets.xcassets 16 | outputs: 17 | - templateName: swift5 18 | params: 19 | forceProvidesNamespaces: true 20 | publicAccess: true 21 | output: Aesthetics/Sources/Aesthetics/Assets+Typesafe.swift 22 | 23 | strings: 24 | - inputs: Settings/Sources/Settings/Resources/en.lproj/Localizable.strings 25 | outputs: 26 | templateName: structured-swift5 27 | output: Settings/Sources/Settings/StringsLocalized.swift 28 | - inputs: CameraFeature/Sources/CameraFeature/Resources/en.lproj/Localizable.strings 29 | outputs: 30 | templateName: structured-swift5 31 | output: CameraFeature/Sources/CameraFeature/StringsLocalized.swift 32 | - inputs: GalleryFeature/Sources/GalleryFeature/Resources/en.lproj/Localizable.strings 33 | outputs: 34 | templateName: structured-swift5 35 | output: GalleryFeature/Sources/GalleryFeature/StringsLocalized.swift 36 | - inputs: Shopfront/Sources/Shopfront/Resources/en.lproj/Localizable.strings 37 | outputs: 38 | templateName: structured-swift5 39 | output: Shopfront/Sources/Shopfront/StringsLocalized.swift 40 | --------------------------------------------------------------------------------