💄 Add a lot of components

This commit is contained in:
Victor Bodinaud
2024-11-29 10:02:38 +01:00
parent 2031687f53
commit 295a0515c3
38 changed files with 914 additions and 5 deletions

View File

@@ -0,0 +1,54 @@
//
// SQCheckbox.swift
// AlloVoisinsSwiftUI
//
// Created by Victor on 25/11/2024.
//
import SwiftUI
struct SQCheckbox: View {
var text: String
@Binding var isChecked: Bool
var errorText: String?
@Binding var isInError: Bool
init(_ text: String, isChecked: Binding<Bool>, errorText: String? = nil, isInError: Binding<Bool> = .constant(false)) {
self.text = text
self._isChecked = isChecked
self.errorText = errorText
self._isInError = isInError
}
var body: some View {
VStack(alignment: .leading, spacing: 4) {
HStack(alignment: .top) {
if isChecked {
SQImage("checked_neutral", height: 20)
} else if isInError {
SQImage("checkbox_unchecked_error", height: 20)
} else {
SQImage("checkbox_unchecked", height: 20)
}
SQText(text)
}
.onTapGesture {
isChecked.toggle()
if isInError && isChecked {
isInError = false
}
}
HStack {
SQIcon(.circle_exclamation, customSize: 13, type: .solid, color: .sqSemanticRed)
SQText("Cette condition est obligatoire.", size: 12, font: .demiBold, textColor: .sqSemanticRed)
}
.isHidden(hidden: !isInError)
}
}
}
#Preview {
SQCheckbox("Je comprends que jengage ma responsabilité sur lexhaustivité et lauthenticité des informations renseignées ci-dessus.", isChecked: .constant(false))
}

View File

@@ -0,0 +1,141 @@
//
// SQImagePicker.swift
// AlloVoisinsSwiftUI
//
// Created by Victor on 27/11/2024.
//
import SwiftUI
struct SQImagePicker: View {
let nbOfImages: Int = 4
var images: [Image] = []
private let itemSpacing: CGFloat = 8
private var columns: [GridItem] {
[
GridItem(.fixed(160), spacing: itemSpacing),
GridItem(.fixed(160), spacing: itemSpacing)
]
}
var body: some View {
VStack(alignment: .leading) {
SQText("Images", font: .demiBold)
LazyVGrid(columns: columns, alignment: .leading) {
ForEach(0 ..< nbOfImages) { _ in
SQImagePickerView()
}
}
}
}
}
struct SQImagePickerView: View {
var image: Image?
@State var showSelection: Bool = false
var body: some View {
VStack {
if let image = image {
image
.frame(width: 160, height: 160)
.background(
RoundedRectangle(cornerRadius: 8)
.fill(Color.sqNeutral(10)))
} else {
HStack {
SQIcon(.camera, size: .xl)
}
.frame(width: 160, height: 160)
.background(
RoundedRectangle(cornerRadius: 8)
.fill(Color.sqNeutral(10)))
}
}
.onTapGesture {
showSelection = true
}
.sheet(isPresented: $showSelection) {
SQImagePickerSelectorSheet()
}
}
}
struct SQImagePickerSelectorSheet: View {
@Environment(\.dismiss) var dismiss
var categoriesImages: [CategoriesImages] = [
CategoriesImages(name: "Entretien - Réparation autres véhicules", pictures: [
"square.and.arrow.up.fill",
"paperplane.circle.fill",
"tray.fill"
]),
CategoriesImages(name: "Plomberie - Installation sanitaire", pictures: [
"xmark.bin.circle.fill"
]),
CategoriesImages(name: "Carrelage", pictures: [
"document.on.document",
"richtext.page.fill.he"
])
]
private let itemSpacing: CGFloat = 8
private var columns: [GridItem] {
[
GridItem(.fixed(160), spacing: itemSpacing),
GridItem(.fixed(160), spacing: itemSpacing)
]
}
var body: some View {
VStack(spacing: 0) {
HStack {
Button {
dismiss()
} label: {
SQIcon(.xmark, size: .l)
}
SQText("Sélectionner une photo", size: 19, font: .bold)
.frame(maxWidth: .infinity)
Spacer()
}
.padding()
ScrollView {
ForEach(categoriesImages, id: \.name) { category in
VStack {
VStack(alignment: .leading) {
SQText(category.name)
LazyVGrid(columns: columns, alignment: .leading) {
ForEach(category.pictures, id: \.self) { picture in
Image(systemName: picture)
.frame(width: 160, height: 120)
.background(
RoundedRectangle(cornerRadius: 8)
.fill(Color.sqNeutral(10)))
}
}
}
.padding()
Rectangle()
.frame(height: 16)
.foregroundColor(Color.sqNeutral(10))
}
}
}
}
}
}
#Preview {
SQImagePicker()
.padding()
}
struct CategoriesImages {
var name: String
var pictures: [String]
}

View File

@@ -0,0 +1,96 @@
//
// SQTextEditor.swift
// AlloVoisinsSwiftUI
//
// Created by Victor on 27/11/2024.
//
import SwiftUI
struct SQTextEditor: View {
var label: String
var placeholder: String
var type: SQTextFieldType = .text
var errorText: String
var icon: SQIcon?
var isDisabled: Bool = false
var isOptional: Bool = false
var tooltipText: String?
@Binding var isInError: Bool
var minCharacters: Int?
var maxCharacters: Int?
@Binding var text: String
@FocusState private var isFocused: Bool
@State private var showTooltip = false
let infoAction: (() -> Void)?
let iconAction: (() -> Void)?
private var accentColor: Color = .sqNeutral(80)
init(_ label: String,
placeholder: String,
type: SQTextFieldType = .text,
errorText: String = "",
text: Binding<String>,
icon: SQIcon? = nil,
isDisabled: Bool = false,
isOptional: Bool = false,
tooltipText: String? = nil,
isInError: Binding<Bool> = .constant(false),
minCharacters: Int? = nil,
maxCharacters: Int? = nil,
infoAction: (() -> Void)? = nil,
iconAction: (() -> Void)? = nil)
{
self.label = label
self.placeholder = placeholder
self.type = type
self.errorText = errorText
self._text = text
self.icon = icon
self.isDisabled = isDisabled
self.isOptional = isOptional
self.tooltipText = tooltipText
self._isInError = isInError
self.minCharacters = minCharacters
self.maxCharacters = maxCharacters
self.infoAction = infoAction
self.iconAction = iconAction
}
var body: some View {
VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 8) {
SQText(label)
Spacer()
if isOptional {
SQText("Optionnel", size: 12, textColor: .sqNeutral(50))
}
}
TextEditor(text: Binding(
get: { self.text },
set: { self.text = String($0.prefix(self.maxCharacters ?? Int.max)) }
))
.onChange(of: self.text, perform: { _ in
self.isInError = false
})
.font(.sq(.medium))
.foregroundStyle(Color.sqNeutral(100))
.tint(accentColor)
.frame(height: 108)
.foregroundStyle(Color.sqNeutral())
.background(isDisabled ? Color.sqNeutral(10) : .clear)
.padding(16)
.overlay(
RoundedRectangle(cornerRadius: 8)
.inset(by: 0.5)
.stroke(isInError ? .sqSemanticRed : isFocused ? accentColor : isDisabled ? Color.sqNeutral(20) : Color.sqNeutral(30), lineWidth: 1)
)
}
}
}
#Preview {
SQTextEditor("Zone de texte", placeholder: "Ex : Pro Solutions propose une gamme de services complète pour tout type de dépannage électroménager. Bénéficiez de nos 10 ans dexpérience ! Devis gratuit", text: .constant("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."))
.padding()
}

View File

@@ -8,8 +8,8 @@
import SwiftUI
enum SQTextFieldType {
case text
case phoneNumber
case text
case phoneNumber
}
struct SQTextField: View {
@@ -20,17 +20,33 @@ struct SQTextField: View {
var icon: SQIcon?
var isDisabled: Bool = false
var isOptional: Bool = false
var tooltipText: String?
@Binding var isInError: Bool
var minCharacters: Int?
var maxCharacters: Int?
@Binding var text: String
@FocusState private var isFocused: Bool
@State private var showTooltip = false
let infoAction: (() -> Void)?
let iconAction: (() -> Void)?
private var accentColor: Color = .sqNeutral(80)
init(_ label: String, placeholder: String, type: SQTextFieldType = .text, errorText: String = "", text: Binding<String>, icon: SQIcon? = nil, isDisabled: Bool = false, isOptional: Bool = false, isInError: Binding<Bool> = .constant(false), minCharacters: Int? = nil, maxCharacters: Int? = nil, infoAction: (() -> Void)? = nil, iconAction: (() -> Void)? = nil) {
init(_ label: String,
placeholder: String,
type: SQTextFieldType = .text,
errorText: String = "",
text: Binding<String>,
icon: SQIcon? = nil,
isDisabled: Bool = false,
isOptional: Bool = false,
tooltipText: String? = nil,
isInError: Binding<Bool> = .constant(false),
minCharacters: Int? = nil,
maxCharacters: Int? = nil,
infoAction: (() -> Void)? = nil,
iconAction: (() -> Void)? = nil)
{
self.label = label
self.placeholder = placeholder
self.type = type
@@ -39,6 +55,7 @@ struct SQTextField: View {
self.icon = icon
self.isDisabled = isDisabled
self.isOptional = isOptional
self.tooltipText = tooltipText
self._isInError = isInError
self.minCharacters = minCharacters
self.maxCharacters = maxCharacters
@@ -50,7 +67,23 @@ struct SQTextField: View {
VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 8) {
SQText(label)
if let infoAction = infoAction {
if let tooltipText = tooltipText {
Button {
withAnimation {
showTooltip.toggle()
}
} label: {
SQIcon(.circle_info, color: .sqNeutral(80))
}
.overlay(
Group {
if showTooltip {
SQTooltip(text: tooltipText, isVisible: $showTooltip)
.fixedSize()
}
}
)
} else if let infoAction = infoAction {
Button {
infoAction()
} label: {
@@ -125,6 +158,18 @@ struct SQTextField: View {
}
}
}
.overlay(
Group {
if showTooltip {
Color.black.opacity(0.001)
.onTapGesture {
withAnimation {
showTooltip = false
}
}
}
}
)
}
private var characterCountText: String {
@@ -164,6 +209,13 @@ struct SQTextField: View {
SQTextField("Label name", placeholder: "Placeholder", text: .constant(""), isDisabled: true)
SQTextField("Label name", placeholder: "Placeholder", errorText: "Champ invalide", text: .constant(""), isInError: .constant(true))
SQTextField("Téléphone", placeholder: "01 23 45 67 89", type: .phoneNumber, text: .constant(""))
SQTextField(
"Numéro de RCS",
placeholder: "RCS VILLE B 123456789",
text: .constant(""),
isOptional: true,
tooltipText: "Vous pouvez trouver votre numéro RCS sur l'extrait Kbis de votre entreprise ou votre extrait K, si vous êtes un entrepreneur individuel.\n\nLe numéro RCS se compose tout d'abord de la mention RCS, puis du numéro d'immatriculation de la ville dans laquelle a été créée la société, d'une lettre et enfin du numéro SIREN à 9 chiffres."
)
}
.padding()
}

View File

@@ -0,0 +1,43 @@
//
// SQTooltip.swift
// AlloVoisinsSwiftUI
//
// Created by Victor on 25/11/2024.
//
import SwiftUI
struct SQTooltip: View {
let text: String
@Binding var isVisible: Bool
@State private var tooltipHeight: CGFloat = 0
private struct Constants {
static let cornerRadius: CGFloat = 8
static let padding: CGFloat = 16
static let maxWidth: CGFloat = 300
static let spacing: CGFloat = 4
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
SQText(text, textColor: .white)
.fixedSize(horizontal: false, vertical: true)
.padding(Constants.padding)
.background(
GeometryReader { geo in
Color.sqNeutral(100)
.clipShape(RoundedRectangle(cornerRadius: Constants.cornerRadius))
.onAppear {
tooltipHeight = geo.size.height
}
}
)
.frame(maxWidth: Constants.maxWidth)
}
.position(x: 210, y: 0)
.offset(y: -(tooltipHeight/2 + Constants.spacing))
.opacity(isVisible ? 1 : 0)
.animation(.easeInOut(duration: 0.2), value: isVisible)
}
}

View File

@@ -39,3 +39,28 @@ extension Font {
.custom(font.rawValue, size: size)
}
}
extension View {
func isHidden(hidden: Bool = false, remove: Bool = false) -> some View {
modifier(
IsHidden(
hidden: hidden,
remove: remove
))
}
}
struct IsHidden: ViewModifier {
var hidden = false
var remove = false
func body(content: Content) -> some View {
if hidden {
if remove {
} else {
content.hidden()
}
} else {
content
}
}
}

View File

@@ -0,0 +1,51 @@
//
// FlyerColorSelectionView.swift
// AlloVoisinsSwiftUI
//
// Created by Victor on 25/11/2024.
//
import SwiftUI
struct FlyerColorSelectionView: View {
@State var goToNext: Bool = false
@State private var applyToAll: Bool = true
@State private var selectedColor: Color = .sqNeutral()
var selectedTemplate: FlyerTemplate
var body: some View {
VStack {
VStack(alignment: .leading, spacing: 32) {
VStack(alignment: .leading, spacing: 16) {
SQColorPicker("Couleur principale", selectedColor: $selectedColor, subtitle: "Choisissez la couleur qui sera appliquée sur vos prospectus.")
SQText("Aperçu", size: 18, font: .bold)
selectedTemplate.imageColorTemplate(isLight: selectedColor.isLight)
.background(selectedColor)
.frame(maxWidth: .infinity)
}
VStack(alignment: .leading) {
Toggle(isOn: $applyToAll) {
SQText("Appliquer cette couleur sur mes cartes de visite, mes devis et mes factures")
}
.tint(Color.sqNeutral(100))
SQText("Nous vous recommandons dappliquer la même couleur sur tous vos documents.", size: 12)
}
Spacer()
}
.padding()
SQFooter {
SQButton("Continuer", color: .sqNeutral(100), textColor: .white) {
self.goToNext.toggle()
}
}
}
.sqNavigationBar(title: "Choix de la couleur ")
.navigationDestination(isPresented: $goToNext) {
CardFormView()
}
}
}
#Preview {
FlyerColorSelectionView(selectedTemplate: .template4)
}

View File

@@ -0,0 +1,171 @@
//
// FlyerFormView.swift
// AlloVoisinsSwiftUI
//
// Created by Victor on 25/11/2024.
//
import SwiftUI
import _PhotosUI_SwiftUI
struct FlyerFormView: View {
@State var title: String = ""
@State var subtitle: String = ""
@State var job: String = ""
@State var showRating: Bool = true
@State var phoneNumber: String = ""
@State var address: String = ""
@State var selectedPicture: PhotosPickerItem?
@State private var image: Image?
@State private var showImagePicker = false
@State private var showPhotoPicker = false
@State private var showActionSheet = false
@State private var useCamera = false
@State private var authentConfirm: Bool = false
@State private var confirmIsInError: Bool = false
var body: some View {
VStack {
ScrollView {
VStack {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .leading) {
SQText("Informations", size: 24, font: .bold)
SQText("Les modifications apportées sur votre prospectus ne seront pas reportées sur votre profil.")
}
VStack(alignment: .leading) {
SQText("Image", font: .demiBold)
ZStack(alignment: .bottomTrailing) {
Button(action: { showActionSheet = true }) {
if let image = image {
image
.resizable()
.scaledToFill()
.frame(width: 160, height: 160)
.clipShape(Circle())
} else {
SQIcon(.camera, customSize: 40)
.frame(width: 160, height: 160)
.background(Color.sqNeutral(10))
.clipShape(Circle())
}
}
if image != nil {
SQIcon(.pen_to_square, size: .m)
.padding(8)
.background(Circle().fill(Color.sqNeutral(15)))
.shadow(color: .sqNeutral(100).opacity(0.1), radius: 4, x: 0, y: 2)
.offset(x: -8, y: -8)
}
}
.frame(maxWidth: .infinity)
}
SQTextField("Titre", placeholder: "Ex : Pro Solutions", errorText: "", text: $title)
SQTextField("Sous-titre", placeholder: "Ex : Martin Dupont", errorText: "", text: $subtitle, isOptional: true)
SQTextField("Métier", placeholder: "Ex : Dépannage électroménager", errorText: "", text: $job, isOptional: true)
VStack(alignment: .leading, spacing: 0) {
Toggle(isOn: $showRating) {
SQText("Afficher ma note AlloVoisins", font: .demiBold)
}
.tint(Color.sqNeutral(100))
HStack(spacing: 4) {
SQIcon(.star, type: .solid, color: .sqGold(50))
SQText("4,7/5 sur", size: 12, font: .demiBold)
SQImage("logo", height: 14)
}
}
.padding(.horizontal, 2)
}
.padding()
Rectangle()
.frame(height: 16)
.foregroundColor(Color.sqNeutral(10))
VStack(alignment: .leading, spacing: 16) {
SQTextEditor("Zone de text", placeholder: "Ex : Pro Solutions propose une gamme de services complète pour tout type de dépannage électroménager. Bénéficiez de nos 10 ans dexpérience ! Devis gratuit", text: .constant(""))
SQTextField("Prestation 1", placeholder: "Ex : Réparation lave-vaisselle", errorText: "", text: $job, isOptional: true)
SQTextField("Prestation 2", placeholder: "Ex : Réparation machine à laver", errorText: "", text: $job, isOptional: true)
SQTextField("Prestation 3", placeholder: "Ex : Réparation four", errorText: "", text: $job, isOptional: true)
SQTextField("Prestation 4", placeholder: "Ex : Réparation outillage", errorText: "", text: $job, isOptional: true)
SQTextField("Prestation 5", placeholder: "Ex : Dépannage électroménager", errorText: "", text: $job, isOptional: true)
}
.padding()
Rectangle()
.frame(height: 16)
.foregroundColor(Color.sqNeutral(10))
VStack(alignment: .leading, spacing: 16) {
SQTextField("Numéro de téléphone", placeholder: "Ex : 06 12 34 56 78", errorText: "", text: $phoneNumber)
SQTextField("Adresse complète", placeholder: "Ex : 1 rue de la gare, 67000 Strasbourg", errorText: "", text: $address)
}
.padding()
Rectangle()
.frame(height: 16)
.foregroundColor(Color.sqNeutral(10))
VStack(alignment: .leading, spacing: 16) {
SQText("Mentions légales obligatoires", size: 18, font: .bold)
SQTextField("Dénomination sociale", placeholder: "Ex : Pro solutions", errorText: "", text: $job, isOptional: true)
SQTextField("Adresse du siège social", placeholder: "Ex : 16 rue de la Redoute, 67500 Haguenau", errorText: "", text: $job, isOptional: true)
VStack(spacing: 0) {
SQTextField("Numéro SIRET", placeholder: "Ex : 12345678901234", errorText: "", text: $job, isOptional: true)
SQText("Le numéro SIRET se compose de 14 chiffres : les 9 chiffres du SIREN + 5 chiffres propres à chaque établissement (NIC).", size: 12, textColor: .sqNeutral(50))
}
SQTextField("Numéro de RCS", placeholder: "Ex : RCS STRASBOURG B 123456789", errorText: "", text: $job, isOptional: true)
SQTextField("Statut juridique", placeholder: "Ex : SARL", errorText: "", text: $job, isOptional: true)
SQTextField("Montant du capital social (€)", placeholder: "Ex : 1 000,00", errorText: "", text: $job, isOptional: true)
SQTextField("Autre champ relatif à votre activité", placeholder: "Ex : Pour votre santé, mangez 5 fruits et légumes par jour", errorText: "", text: $job, isOptional: true)
SQCheckbox("Je comprends que jengage ma responsabilité sur lexhaustivité et lauthenticité des informations renseignées ci-dessus.", isChecked: $authentConfirm, isInError: $confirmIsInError)
}
.padding()
}
}
SQFooter {
SQButton("Aperçu", color: .sqNeutral(100), textColor: .sqNeutral(100), icon: SQIcon(.eye, color: .sqNeutral(100)), isFull: false) {}
.sqStyle()
SQButton("Imprimer", color: .sqNeutral(100), textColor: .white, icon: SQIcon(.print, color: .white)) {
if authentConfirm == false {
self.confirmIsInError = true
}
}
.sqStyle()
}
}
.confirmationDialog("Choisir une image", isPresented: $showActionSheet, actions: {
Button("Appareil photo") {
useCamera = true
showImagePicker = true
}
Button("Galerie") {
useCamera = false
showPhotoPicker = true
}
Button("Annuler", role: .cancel) {}
})
.photosPicker(isPresented: $showPhotoPicker, selection: $selectedPicture)
.sheet(isPresented: $showImagePicker) {
if useCamera {
ImagePicker(image: $image, sourceType: .camera)
}
}
.task(id: selectedPicture) {
if let data = try? await selectedPicture?.loadTransferable(type: Image.self) {
image = data
}
}
.sqNavigationBar(title: "Mon prospectus")
}
}
#Preview {
FlyerFormView()
}

View File

@@ -0,0 +1,18 @@
//
// FlyerPrintView.swift
// AlloVoisinsSwiftUI
//
// Created by Victor on 25/11/2024.
//
import SwiftUI
struct FlyerPrintView: View {
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
}
}
#Preview {
FlyerPrintView()
}

View File

@@ -0,0 +1,108 @@
//
// FlyerTemplateSelectionView.swift
// AlloVoisinsSwiftUI
//
// Created by Victor on 25/11/2024.
//
import SwiftUI
enum FlyerTemplate: String, CaseIterable {
case template1
case template2
case template3
case template4
var image: SQImage {
switch self {
case .template1:
SQImage("flyer_template_1", height: 284)
case .template2:
SQImage("flyer_template_2", height: 284)
case .template3:
SQImage("flyer_template_3", height: 284)
case .template4:
SQImage("flyer_template_4", height: 284)
}
}
var nbOfPictures: Int {
switch self {
case .template1:
1
case .template2:
3
case .template3:
4
case .template4:
2
}
}
func imageColorTemplate(isLight: Bool) -> SQImage {
switch self {
case .template1:
if isLight {
return SQImage("flyer_color_template_1_black", height: 284)
} else {
return SQImage("flyer_color_template_1_white", height: 284)
}
case .template2:
return SQImage("flyer_color_template_2", height: 284)
case .template3:
if isLight {
return SQImage("flyer_color_template_3_black", height: 284)
} else {
return SQImage("flyer_color_template_3_white", height: 284)
}
case .template4:
if isLight {
return SQImage("flyer_color_template_4_black", height: 284)
} else {
return SQImage("flyer_color_template_4_white", height: 284)
}
}
}
}
struct FlyerTemplateSelectionView: View {
@State var goToNext: Bool = false
@State var selectedTemplate: FlyerTemplate?
var body: some View {
VStack {
ScrollView {
LazyVStack(spacing: 16) {
ForEach(FlyerTemplate.allCases, id: \.self) { template in
template.image
.overlay(
Rectangle()
.inset(by: selectedTemplate == template ? 1 : 0.5)
.stroke(selectedTemplate == template ? Color.sqNeutral(100) : Color.sqNeutral(20), lineWidth: selectedTemplate == template ? 2 : 1)
)
.opacity(selectedTemplate != nil ? selectedTemplate == template ? 1 : 0.5 : 1)
.onTapGesture {
selectedTemplate = template
}
}
}
}
SQFooter {
SQButton("Continuer", color: .sqNeutral(100), textColor: .white) {
if selectedTemplate != nil {
goToNext.toggle()
}
}
.disabled(selectedTemplate == nil)
}
}
.sqNavigationBar(title: "Choix du modèle")
.navigationDestination(isPresented: $goToNext) {
// FlyerColorSelectionView(selectedTemplate: selectedTemplate ?? FlyerTemplate.template1)
}
}
}
#Preview {
FlyerTemplateSelectionView()
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "check.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "flyer_color_template_1_black.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "flyer_color_template_1.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "flyer_color_template_2.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "flyer_color_template_3_black.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "flyer_color_template_3.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "flyer_color_template_4_black.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "flyer_color_template_4.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "prospectus 1.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "prospectus 2.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "prospectus 3.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "prospectus 4.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

View File

@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "image (1).png",
"filename" : "image.png",
"idiom" : "universal"
}
],

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 KiB