├── QRCodeSwiftUI.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── ulanagritcina.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── user.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── ulanagritcina.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ └── user.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── QRCodeSwiftUI ├── .DS_Store ├── Core │ ├── Generate QR │ │ ├── GenerateQRView.swift │ │ ├── GenerateQRViewModel.swift │ │ └── Generated │ │ │ ├── GeneratedQRView.swift │ │ │ └── GeneratedQRViewModel.swift │ ├── SavedCodes │ │ ├── QRCodeDitail │ │ │ ├── QRCodeDetailView.swift │ │ │ └── QRCodeDetailViewModel.swift │ │ ├── SavedCodeRowView.swift │ │ ├── SavedCodesView.swift │ │ └── SavedCodesViewModel.swift │ ├── Settings │ │ ├── SettingsView.swift │ │ └── SettingsViewModel.swift │ └── TabView │ │ └── TabViewView.swift ├── DesignSystem │ ├── BackgroundView.swift │ ├── ButtonView.swift │ ├── PhotoPickerView.swift │ ├── QrView.swift │ ├── ShareQRButton.swift │ └── ViewModifires │ │ ├── AppTextFieldStyle.swift │ │ └── CircleModifier.swift ├── Info.plist ├── Managers │ ├── QRGeneratorManager.swift │ ├── RequestReviewManager.swift │ └── UserDefaultsManager.swift ├── Models │ ├── QRCode.swift │ └── RGBColor.swift └── SupportingFiles │ ├── .DS_Store │ ├── Assets.xcassets │ ├── .DS_Store │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── 100.png │ │ ├── 1024.png │ │ ├── 114.png │ │ ├── 120.png │ │ ├── 128.png │ │ ├── 144.png │ │ ├── 152.png │ │ ├── 16.png │ │ ├── 167.png │ │ ├── 172.png │ │ ├── 180.png │ │ ├── 196.png │ │ ├── 20.png │ │ ├── 216.png │ │ ├── 256.png │ │ ├── 29.png │ │ ├── 32.png │ │ ├── 40.png │ │ ├── 48.png │ │ ├── 50.png │ │ ├── 512.png │ │ ├── 55.png │ │ ├── 57.png │ │ ├── 58.png │ │ ├── 60.png │ │ ├── 64.png │ │ ├── 72.png │ │ ├── 76.png │ │ ├── 80.png │ │ ├── 87.png │ │ ├── 88.png │ │ └── Contents.json │ ├── Colors │ │ ├── Contents.json │ │ ├── background.colorset │ │ │ └── Contents.json │ │ ├── button.colorset │ │ │ └── Contents.json │ │ ├── cardBackground.colorset │ │ │ └── Contents.json │ │ ├── grabber.colorset │ │ │ └── Contents.json │ │ ├── lightShadow.colorset │ │ │ └── Contents.json │ │ ├── shadow.colorset │ │ │ └── Contents.json │ │ ├── sheet.colorset │ │ │ └── Contents.json │ │ └── text.colorset │ │ │ └── Contents.json │ ├── Contents.json │ └── Images │ │ ├── Contents.json │ │ ├── bac.imageset │ │ ├── Contents.json │ │ └── bac.png │ │ ├── defaultQRImage.imageset │ │ ├── Contents.json │ │ └── defaultQRImage.jpeg │ │ └── ww.imageset │ │ ├── Contents.json │ │ └── Group 1248.png │ ├── Extensions │ ├── Color + Extension.swift │ └── UIApplication+Extension.swift │ ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json │ └── QRCodeSwiftUIApp.swift └── README.md /QRCodeSwiftUI.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0E3023ED28CF51A300037184 /* ShareQRButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3023EC28CF51A300037184 /* ShareQRButton.swift */; }; 11 | 0E3D0DD42B029C9400F5A55E /* UserDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3D0DD32B029C9400F5A55E /* UserDefaultsManager.swift */; }; 12 | 0E3D0DD62B029F2B00F5A55E /* GeneratedQRViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3D0DD52B029F2B00F5A55E /* GeneratedQRViewModel.swift */; }; 13 | 0E3E3F872B10F83A006DEF43 /* AppTextFieldStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E3E3F862B10F83A006DEF43 /* AppTextFieldStyle.swift */; }; 14 | 0E5C14A828CB4AFE0021FB3E /* UIApplication+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E5C14A728CB4AFE0021FB3E /* UIApplication+Extension.swift */; }; 15 | 0E6878E02A4A115900DC7D77 /* TabViewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6878DF2A4A115900DC7D77 /* TabViewView.swift */; }; 16 | 0E77314F28CB4FB800B10086 /* GenerateQRViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E77314E28CB4FB800B10086 /* GenerateQRViewModel.swift */; }; 17 | 0E77315428CB5B9200B10086 /* SavedCodesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E77315328CB5B9200B10086 /* SavedCodesView.swift */; }; 18 | 0E7D54D228CCB5F200F511A4 /* QRCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7D54D128CCB5F200F511A4 /* QRCode.swift */; }; 19 | 0E7D54D428CCD67800F511A4 /* SavedCodeRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7D54D328CCD67800F511A4 /* SavedCodeRowView.swift */; }; 20 | 0E7D54D628CCF32400F511A4 /* SavedCodesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7D54D528CCF32400F511A4 /* SavedCodesViewModel.swift */; }; 21 | 0E7D54D828CCF36C00F511A4 /* QRCodeDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7D54D728CCF36C00F511A4 /* QRCodeDetailView.swift */; }; 22 | 0E7F4D9A2945E600000EFB14 /* Color + Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F4D992945E600000EFB14 /* Color + Extension.swift */; }; 23 | 0E7F4D9C2945ECFF000EFB14 /* ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F4D9B2945ECFF000EFB14 /* ButtonView.swift */; }; 24 | 0E8732EF28C8AE2D00645115 /* QRCodeSwiftUIApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8732EE28C8AE2D00645115 /* QRCodeSwiftUIApp.swift */; }; 25 | 0E8732F128C8AE2D00645115 /* GenerateQRView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8732F028C8AE2D00645115 /* GenerateQRView.swift */; }; 26 | 0E8732F328C8AE3100645115 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E8732F228C8AE3100645115 /* Assets.xcassets */; }; 27 | 0E8732F628C8AE3100645115 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E8732F528C8AE3100645115 /* Preview Assets.xcassets */; }; 28 | 0EA2C42F2B5BAA9E001F8313 /* CircleModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA2C42E2B5BAA9E001F8313 /* CircleModifier.swift */; }; 29 | 0EA7D5132B013AD6005C9EC1 /* QRGeneratorManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA7D5122B013AD6005C9EC1 /* QRGeneratorManager.swift */; }; 30 | 0EA7D5152B014082005C9EC1 /* BackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA7D5142B014082005C9EC1 /* BackgroundView.swift */; }; 31 | 0EA7D5172B0142B8005C9EC1 /* GeneratedQRView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA7D5162B0142B8005C9EC1 /* GeneratedQRView.swift */; }; 32 | 0EA7D51A2B0146D7005C9EC1 /* QrView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA7D5192B0146D7005C9EC1 /* QrView.swift */; }; 33 | 0EB88E4E2B0524A600D44819 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB88E4D2B0524A600D44819 /* SettingsView.swift */; }; 34 | 0EC233592B0D1A9D002F9123 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EC233582B0D1A9D002F9123 /* SettingsViewModel.swift */; }; 35 | 0ECE42022B0525DF005EB685 /* RequestReviewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECE42012B0525DE005EB685 /* RequestReviewManager.swift */; }; 36 | 0EF94FEC2D4FA7A5003FA0CC /* PhotoPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF94FEB2D4FA7A5003FA0CC /* PhotoPickerView.swift */; }; 37 | CEC20A092B04F0C900E5113F /* QRCodeDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC20A082B04F0C900E5113F /* QRCodeDetailViewModel.swift */; }; 38 | CEE654A52B0B783C00A25EAF /* RGBColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE654A42B0B783C00A25EAF /* RGBColor.swift */; }; 39 | /* End PBXBuildFile section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 0E3023EC28CF51A300037184 /* ShareQRButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareQRButton.swift; sourceTree = ""; }; 43 | 0E3D0DD32B029C9400F5A55E /* UserDefaultsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsManager.swift; sourceTree = ""; }; 44 | 0E3D0DD52B029F2B00F5A55E /* GeneratedQRViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneratedQRViewModel.swift; sourceTree = ""; }; 45 | 0E3E3F862B10F83A006DEF43 /* AppTextFieldStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTextFieldStyle.swift; sourceTree = ""; }; 46 | 0E5C14A728CB4AFE0021FB3E /* UIApplication+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+Extension.swift"; sourceTree = ""; }; 47 | 0E6878DF2A4A115900DC7D77 /* TabViewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabViewView.swift; sourceTree = ""; }; 48 | 0E77314E28CB4FB800B10086 /* GenerateQRViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateQRViewModel.swift; sourceTree = ""; }; 49 | 0E77315328CB5B9200B10086 /* SavedCodesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SavedCodesView.swift; sourceTree = ""; }; 50 | 0E7D54D128CCB5F200F511A4 /* QRCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCode.swift; sourceTree = ""; }; 51 | 0E7D54D328CCD67800F511A4 /* SavedCodeRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SavedCodeRowView.swift; sourceTree = ""; }; 52 | 0E7D54D528CCF32400F511A4 /* SavedCodesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SavedCodesViewModel.swift; sourceTree = ""; }; 53 | 0E7D54D728CCF36C00F511A4 /* QRCodeDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeDetailView.swift; sourceTree = ""; }; 54 | 0E7F4D992945E600000EFB14 /* Color + Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color + Extension.swift"; sourceTree = ""; }; 55 | 0E7F4D9B2945ECFF000EFB14 /* ButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonView.swift; sourceTree = ""; }; 56 | 0E8732EB28C8AE2D00645115 /* QR Generator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "QR Generator.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 0E8732EE28C8AE2D00645115 /* QRCodeSwiftUIApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeSwiftUIApp.swift; sourceTree = ""; }; 58 | 0E8732F028C8AE2D00645115 /* GenerateQRView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateQRView.swift; sourceTree = ""; }; 59 | 0E8732F228C8AE3100645115 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 60 | 0E8732F528C8AE3100645115 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 61 | 0EA2C42E2B5BAA9E001F8313 /* CircleModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleModifier.swift; sourceTree = ""; }; 62 | 0EA7D5122B013AD6005C9EC1 /* QRGeneratorManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRGeneratorManager.swift; sourceTree = ""; }; 63 | 0EA7D5142B014082005C9EC1 /* BackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundView.swift; sourceTree = ""; }; 64 | 0EA7D5162B0142B8005C9EC1 /* GeneratedQRView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneratedQRView.swift; sourceTree = ""; }; 65 | 0EA7D5192B0146D7005C9EC1 /* QrView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QrView.swift; sourceTree = ""; }; 66 | 0EB88E4D2B0524A600D44819 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; 67 | 0EC233582B0D1A9D002F9123 /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = ""; }; 68 | 0ECE42012B0525DE005EB685 /* RequestReviewManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestReviewManager.swift; sourceTree = ""; }; 69 | 0EF94FEB2D4FA7A5003FA0CC /* PhotoPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPickerView.swift; sourceTree = ""; }; 70 | CEC20A082B04F0C900E5113F /* QRCodeDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeDetailViewModel.swift; sourceTree = ""; }; 71 | CEE654A42B0B783C00A25EAF /* RGBColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RGBColor.swift; sourceTree = ""; }; 72 | /* End PBXFileReference section */ 73 | 74 | /* Begin PBXFrameworksBuildPhase section */ 75 | 0E8732E828C8AE2D00645115 /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | ); 80 | runOnlyForDeploymentPostprocessing = 0; 81 | }; 82 | /* End PBXFrameworksBuildPhase section */ 83 | 84 | /* Begin PBXGroup section */ 85 | 0E05638A28D1E9EB005C9476 /* QRCodeDitail */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | CEC20A082B04F0C900E5113F /* QRCodeDetailViewModel.swift */, 89 | 0E7D54D728CCF36C00F511A4 /* QRCodeDetailView.swift */, 90 | ); 91 | path = QRCodeDitail; 92 | sourceTree = ""; 93 | }; 94 | 0E3E3F852B10F829006DEF43 /* ViewModifires */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 0E3E3F862B10F83A006DEF43 /* AppTextFieldStyle.swift */, 98 | 0EA2C42E2B5BAA9E001F8313 /* CircleModifier.swift */, 99 | ); 100 | path = ViewModifires; 101 | sourceTree = ""; 102 | }; 103 | 0E5C14A628CB4AE50021FB3E /* Extensions */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 0E5C14A728CB4AFE0021FB3E /* UIApplication+Extension.swift */, 107 | 0E7F4D992945E600000EFB14 /* Color + Extension.swift */, 108 | ); 109 | path = Extensions; 110 | sourceTree = ""; 111 | }; 112 | 0E6878E12A4A125500DC7D77 /* TabView */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 0E6878DF2A4A115900DC7D77 /* TabViewView.swift */, 116 | ); 117 | path = TabView; 118 | sourceTree = ""; 119 | }; 120 | 0E6878E22A4A159000DC7D77 /* Core */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 0E6878E12A4A125500DC7D77 /* TabView */, 124 | 0E77314D28CB4F9E00B10086 /* Generate QR */, 125 | 0E77315528CB5B9500B10086 /* SavedCodes */, 126 | 0EB88E4C2B05249700D44819 /* Settings */, 127 | ); 128 | path = Core; 129 | sourceTree = ""; 130 | }; 131 | 0E6878E32A4A15A900DC7D77 /* SupportingFiles */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 0E8732F228C8AE3100645115 /* Assets.xcassets */, 135 | 0E8732F428C8AE3100645115 /* Preview Content */, 136 | 0E8732EE28C8AE2D00645115 /* QRCodeSwiftUIApp.swift */, 137 | 0E5C14A628CB4AE50021FB3E /* Extensions */, 138 | ); 139 | path = SupportingFiles; 140 | sourceTree = ""; 141 | }; 142 | 0E77314D28CB4F9E00B10086 /* Generate QR */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | 0E77314E28CB4FB800B10086 /* GenerateQRViewModel.swift */, 146 | 0E8732F028C8AE2D00645115 /* GenerateQRView.swift */, 147 | 0EA7D5182B014683005C9EC1 /* Generated */, 148 | ); 149 | path = "Generate QR"; 150 | sourceTree = ""; 151 | }; 152 | 0E77315528CB5B9500B10086 /* SavedCodes */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 0E7D54D528CCF32400F511A4 /* SavedCodesViewModel.swift */, 156 | 0E77315328CB5B9200B10086 /* SavedCodesView.swift */, 157 | 0E7D54D328CCD67800F511A4 /* SavedCodeRowView.swift */, 158 | 0E05638A28D1E9EB005C9476 /* QRCodeDitail */, 159 | ); 160 | path = SavedCodes; 161 | sourceTree = ""; 162 | }; 163 | 0E7D54D028CCB5DA00F511A4 /* Models */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 0E7D54D128CCB5F200F511A4 /* QRCode.swift */, 167 | CEE654A42B0B783C00A25EAF /* RGBColor.swift */, 168 | ); 169 | path = Models; 170 | sourceTree = ""; 171 | }; 172 | 0E82A0CF28CDD7A200AB1AE3 /* DesignSystem */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 0EF94FEB2D4FA7A5003FA0CC /* PhotoPickerView.swift */, 176 | 0E3E3F852B10F829006DEF43 /* ViewModifires */, 177 | 0EA7D5142B014082005C9EC1 /* BackgroundView.swift */, 178 | 0E7F4D9B2945ECFF000EFB14 /* ButtonView.swift */, 179 | 0E3023EC28CF51A300037184 /* ShareQRButton.swift */, 180 | 0EA7D5192B0146D7005C9EC1 /* QrView.swift */, 181 | ); 182 | path = DesignSystem; 183 | sourceTree = ""; 184 | }; 185 | 0E8732E228C8AE2C00645115 = { 186 | isa = PBXGroup; 187 | children = ( 188 | 0E8732ED28C8AE2D00645115 /* QRCodeSwiftUI */, 189 | 0E8732EC28C8AE2D00645115 /* Products */, 190 | ); 191 | sourceTree = ""; 192 | }; 193 | 0E8732EC28C8AE2D00645115 /* Products */ = { 194 | isa = PBXGroup; 195 | children = ( 196 | 0E8732EB28C8AE2D00645115 /* QR Generator.app */, 197 | ); 198 | name = Products; 199 | sourceTree = ""; 200 | }; 201 | 0E8732ED28C8AE2D00645115 /* QRCodeSwiftUI */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | 0E6878E32A4A15A900DC7D77 /* SupportingFiles */, 205 | 0EA7D5112B013AC8005C9EC1 /* Managers */, 206 | 0E7D54D028CCB5DA00F511A4 /* Models */, 207 | 0E82A0CF28CDD7A200AB1AE3 /* DesignSystem */, 208 | 0E6878E22A4A159000DC7D77 /* Core */, 209 | ); 210 | path = QRCodeSwiftUI; 211 | sourceTree = ""; 212 | }; 213 | 0E8732F428C8AE3100645115 /* Preview Content */ = { 214 | isa = PBXGroup; 215 | children = ( 216 | 0E8732F528C8AE3100645115 /* Preview Assets.xcassets */, 217 | ); 218 | path = "Preview Content"; 219 | sourceTree = ""; 220 | }; 221 | 0EA7D5112B013AC8005C9EC1 /* Managers */ = { 222 | isa = PBXGroup; 223 | children = ( 224 | 0ECE42012B0525DE005EB685 /* RequestReviewManager.swift */, 225 | 0EA7D5122B013AD6005C9EC1 /* QRGeneratorManager.swift */, 226 | 0E3D0DD32B029C9400F5A55E /* UserDefaultsManager.swift */, 227 | ); 228 | path = Managers; 229 | sourceTree = ""; 230 | }; 231 | 0EA7D5182B014683005C9EC1 /* Generated */ = { 232 | isa = PBXGroup; 233 | children = ( 234 | 0E3D0DD52B029F2B00F5A55E /* GeneratedQRViewModel.swift */, 235 | 0EA7D5162B0142B8005C9EC1 /* GeneratedQRView.swift */, 236 | ); 237 | path = Generated; 238 | sourceTree = ""; 239 | }; 240 | 0EB88E4C2B05249700D44819 /* Settings */ = { 241 | isa = PBXGroup; 242 | children = ( 243 | 0EB88E4D2B0524A600D44819 /* SettingsView.swift */, 244 | 0EC233582B0D1A9D002F9123 /* SettingsViewModel.swift */, 245 | ); 246 | path = Settings; 247 | sourceTree = ""; 248 | }; 249 | /* End PBXGroup section */ 250 | 251 | /* Begin PBXNativeTarget section */ 252 | 0E8732EA28C8AE2D00645115 /* QRCodeSwiftUI */ = { 253 | isa = PBXNativeTarget; 254 | buildConfigurationList = 0E8732F928C8AE3100645115 /* Build configuration list for PBXNativeTarget "QRCodeSwiftUI" */; 255 | buildPhases = ( 256 | 0E8732E728C8AE2D00645115 /* Sources */, 257 | 0E8732E828C8AE2D00645115 /* Frameworks */, 258 | 0E8732E928C8AE2D00645115 /* Resources */, 259 | ); 260 | buildRules = ( 261 | ); 262 | dependencies = ( 263 | ); 264 | name = QRCodeSwiftUI; 265 | packageProductDependencies = ( 266 | ); 267 | productName = QRCodeSwiftUI; 268 | productReference = 0E8732EB28C8AE2D00645115 /* QR Generator.app */; 269 | productType = "com.apple.product-type.application"; 270 | }; 271 | /* End PBXNativeTarget section */ 272 | 273 | /* Begin PBXProject section */ 274 | 0E8732E328C8AE2C00645115 /* Project object */ = { 275 | isa = PBXProject; 276 | attributes = { 277 | BuildIndependentTargetsInParallel = 1; 278 | LastSwiftUpdateCheck = 1300; 279 | LastUpgradeCheck = 1500; 280 | TargetAttributes = { 281 | 0E8732EA28C8AE2D00645115 = { 282 | CreatedOnToolsVersion = 13.0; 283 | }; 284 | }; 285 | }; 286 | buildConfigurationList = 0E8732E628C8AE2C00645115 /* Build configuration list for PBXProject "QRCodeSwiftUI" */; 287 | compatibilityVersion = "Xcode 13.0"; 288 | developmentRegion = en; 289 | hasScannedForEncodings = 0; 290 | knownRegions = ( 291 | en, 292 | Base, 293 | ); 294 | mainGroup = 0E8732E228C8AE2C00645115; 295 | packageReferences = ( 296 | ); 297 | productRefGroup = 0E8732EC28C8AE2D00645115 /* Products */; 298 | projectDirPath = ""; 299 | projectRoot = ""; 300 | targets = ( 301 | 0E8732EA28C8AE2D00645115 /* QRCodeSwiftUI */, 302 | ); 303 | }; 304 | /* End PBXProject section */ 305 | 306 | /* Begin PBXResourcesBuildPhase section */ 307 | 0E8732E928C8AE2D00645115 /* Resources */ = { 308 | isa = PBXResourcesBuildPhase; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | 0E8732F628C8AE3100645115 /* Preview Assets.xcassets in Resources */, 312 | 0E8732F328C8AE3100645115 /* Assets.xcassets in Resources */, 313 | ); 314 | runOnlyForDeploymentPostprocessing = 0; 315 | }; 316 | /* End PBXResourcesBuildPhase section */ 317 | 318 | /* Begin PBXSourcesBuildPhase section */ 319 | 0E8732E728C8AE2D00645115 /* Sources */ = { 320 | isa = PBXSourcesBuildPhase; 321 | buildActionMask = 2147483647; 322 | files = ( 323 | 0ECE42022B0525DF005EB685 /* RequestReviewManager.swift in Sources */, 324 | 0E8732F128C8AE2D00645115 /* GenerateQRView.swift in Sources */, 325 | CEE654A52B0B783C00A25EAF /* RGBColor.swift in Sources */, 326 | 0E8732EF28C8AE2D00645115 /* QRCodeSwiftUIApp.swift in Sources */, 327 | 0EA7D5172B0142B8005C9EC1 /* GeneratedQRView.swift in Sources */, 328 | 0E7F4D9C2945ECFF000EFB14 /* ButtonView.swift in Sources */, 329 | 0E5C14A828CB4AFE0021FB3E /* UIApplication+Extension.swift in Sources */, 330 | 0E3D0DD62B029F2B00F5A55E /* GeneratedQRViewModel.swift in Sources */, 331 | 0E3E3F872B10F83A006DEF43 /* AppTextFieldStyle.swift in Sources */, 332 | 0E3D0DD42B029C9400F5A55E /* UserDefaultsManager.swift in Sources */, 333 | 0EC233592B0D1A9D002F9123 /* SettingsViewModel.swift in Sources */, 334 | 0E7D54D828CCF36C00F511A4 /* QRCodeDetailView.swift in Sources */, 335 | 0E7D54D428CCD67800F511A4 /* SavedCodeRowView.swift in Sources */, 336 | 0EA7D5152B014082005C9EC1 /* BackgroundView.swift in Sources */, 337 | 0E3023ED28CF51A300037184 /* ShareQRButton.swift in Sources */, 338 | 0E6878E02A4A115900DC7D77 /* TabViewView.swift in Sources */, 339 | 0E77314F28CB4FB800B10086 /* GenerateQRViewModel.swift in Sources */, 340 | 0EB88E4E2B0524A600D44819 /* SettingsView.swift in Sources */, 341 | 0EA2C42F2B5BAA9E001F8313 /* CircleModifier.swift in Sources */, 342 | 0E7D54D228CCB5F200F511A4 /* QRCode.swift in Sources */, 343 | 0E7D54D628CCF32400F511A4 /* SavedCodesViewModel.swift in Sources */, 344 | CEC20A092B04F0C900E5113F /* QRCodeDetailViewModel.swift in Sources */, 345 | 0EF94FEC2D4FA7A5003FA0CC /* PhotoPickerView.swift in Sources */, 346 | 0E77315428CB5B9200B10086 /* SavedCodesView.swift in Sources */, 347 | 0E7F4D9A2945E600000EFB14 /* Color + Extension.swift in Sources */, 348 | 0EA7D5132B013AD6005C9EC1 /* QRGeneratorManager.swift in Sources */, 349 | 0EA7D51A2B0146D7005C9EC1 /* QrView.swift in Sources */, 350 | ); 351 | runOnlyForDeploymentPostprocessing = 0; 352 | }; 353 | /* End PBXSourcesBuildPhase section */ 354 | 355 | /* Begin XCBuildConfiguration section */ 356 | 0E8732F728C8AE3100645115 /* Debug */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | ALWAYS_SEARCH_USER_PATHS = NO; 360 | CLANG_ANALYZER_NONNULL = YES; 361 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 362 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 363 | CLANG_CXX_LIBRARY = "libc++"; 364 | CLANG_ENABLE_MODULES = YES; 365 | CLANG_ENABLE_OBJC_ARC = YES; 366 | CLANG_ENABLE_OBJC_WEAK = YES; 367 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 368 | CLANG_WARN_BOOL_CONVERSION = YES; 369 | CLANG_WARN_COMMA = YES; 370 | CLANG_WARN_CONSTANT_CONVERSION = YES; 371 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 372 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 373 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 374 | CLANG_WARN_EMPTY_BODY = YES; 375 | CLANG_WARN_ENUM_CONVERSION = YES; 376 | CLANG_WARN_INFINITE_RECURSION = YES; 377 | CLANG_WARN_INT_CONVERSION = YES; 378 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 379 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 380 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 381 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 382 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 383 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 384 | CLANG_WARN_STRICT_PROTOTYPES = YES; 385 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 386 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 387 | CLANG_WARN_UNREACHABLE_CODE = YES; 388 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 389 | COPY_PHASE_STRIP = NO; 390 | DEBUG_INFORMATION_FORMAT = dwarf; 391 | ENABLE_STRICT_OBJC_MSGSEND = YES; 392 | ENABLE_TESTABILITY = YES; 393 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 394 | GCC_C_LANGUAGE_STANDARD = gnu11; 395 | GCC_DYNAMIC_NO_PIC = NO; 396 | GCC_NO_COMMON_BLOCKS = YES; 397 | GCC_OPTIMIZATION_LEVEL = 0; 398 | GCC_PREPROCESSOR_DEFINITIONS = ( 399 | "DEBUG=1", 400 | "$(inherited)", 401 | ); 402 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 403 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 404 | GCC_WARN_UNDECLARED_SELECTOR = YES; 405 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 406 | GCC_WARN_UNUSED_FUNCTION = YES; 407 | GCC_WARN_UNUSED_VARIABLE = YES; 408 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 409 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 410 | MTL_FAST_MATH = YES; 411 | ONLY_ACTIVE_ARCH = YES; 412 | SDKROOT = iphoneos; 413 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 414 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 415 | }; 416 | name = Debug; 417 | }; 418 | 0E8732F828C8AE3100645115 /* Release */ = { 419 | isa = XCBuildConfiguration; 420 | buildSettings = { 421 | ALWAYS_SEARCH_USER_PATHS = NO; 422 | CLANG_ANALYZER_NONNULL = YES; 423 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 424 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 425 | CLANG_CXX_LIBRARY = "libc++"; 426 | CLANG_ENABLE_MODULES = YES; 427 | CLANG_ENABLE_OBJC_ARC = YES; 428 | CLANG_ENABLE_OBJC_WEAK = YES; 429 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 430 | CLANG_WARN_BOOL_CONVERSION = YES; 431 | CLANG_WARN_COMMA = YES; 432 | CLANG_WARN_CONSTANT_CONVERSION = YES; 433 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 434 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 435 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 436 | CLANG_WARN_EMPTY_BODY = YES; 437 | CLANG_WARN_ENUM_CONVERSION = YES; 438 | CLANG_WARN_INFINITE_RECURSION = YES; 439 | CLANG_WARN_INT_CONVERSION = YES; 440 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 441 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 442 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 443 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 444 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 445 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 446 | CLANG_WARN_STRICT_PROTOTYPES = YES; 447 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 448 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 449 | CLANG_WARN_UNREACHABLE_CODE = YES; 450 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 451 | COPY_PHASE_STRIP = NO; 452 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 453 | ENABLE_NS_ASSERTIONS = NO; 454 | ENABLE_STRICT_OBJC_MSGSEND = YES; 455 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 456 | GCC_C_LANGUAGE_STANDARD = gnu11; 457 | GCC_NO_COMMON_BLOCKS = YES; 458 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 459 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 460 | GCC_WARN_UNDECLARED_SELECTOR = YES; 461 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 462 | GCC_WARN_UNUSED_FUNCTION = YES; 463 | GCC_WARN_UNUSED_VARIABLE = YES; 464 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 465 | MTL_ENABLE_DEBUG_INFO = NO; 466 | MTL_FAST_MATH = YES; 467 | SDKROOT = iphoneos; 468 | SWIFT_COMPILATION_MODE = wholemodule; 469 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 470 | VALIDATE_PRODUCT = YES; 471 | }; 472 | name = Release; 473 | }; 474 | 0E8732FA28C8AE3100645115 /* Debug */ = { 475 | isa = XCBuildConfiguration; 476 | buildSettings = { 477 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 478 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 479 | CODE_SIGN_STYLE = Automatic; 480 | CURRENT_PROJECT_VERSION = 8; 481 | DEVELOPMENT_ASSET_PATHS = ""; 482 | DEVELOPMENT_TEAM = 86SKTK882J; 483 | ENABLE_PREVIEWS = YES; 484 | GENERATE_INFOPLIST_FILE = YES; 485 | INFOPLIST_FILE = QRCodeSwiftUI/Info.plist; 486 | INFOPLIST_KEY_CFBundleDisplayName = "My QR"; 487 | INFOPLIST_KEY_LSApplicationCategoryType = ""; 488 | INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = ""; 489 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 490 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 491 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 492 | INFOPLIST_KEY_WKWatchOnly = NO; 493 | IPHONEOS_DEPLOYMENT_TARGET = 15.6; 494 | LD_RUNPATH_SEARCH_PATHS = ( 495 | "$(inherited)", 496 | "@executable_path/Frameworks", 497 | ); 498 | MARKETING_VERSION = 2.1.4; 499 | PRODUCT_BUNDLE_IDENTIFIER = "ugritchina-icloud.com.QRCodeSwiftUI"; 500 | PRODUCT_NAME = "QR Generator"; 501 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 502 | SUPPORTS_MACCATALYST = NO; 503 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 504 | SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; 505 | SWIFT_EMIT_LOC_STRINGS = YES; 506 | SWIFT_VERSION = 5.0; 507 | TARGETED_DEVICE_FAMILY = 1; 508 | }; 509 | name = Debug; 510 | }; 511 | 0E8732FB28C8AE3100645115 /* Release */ = { 512 | isa = XCBuildConfiguration; 513 | buildSettings = { 514 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 515 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 516 | CODE_SIGN_STYLE = Automatic; 517 | CURRENT_PROJECT_VERSION = 8; 518 | DEVELOPMENT_ASSET_PATHS = ""; 519 | DEVELOPMENT_TEAM = 86SKTK882J; 520 | ENABLE_PREVIEWS = YES; 521 | GENERATE_INFOPLIST_FILE = YES; 522 | INFOPLIST_FILE = QRCodeSwiftUI/Info.plist; 523 | INFOPLIST_KEY_CFBundleDisplayName = "My QR"; 524 | INFOPLIST_KEY_LSApplicationCategoryType = ""; 525 | INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = ""; 526 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 527 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 528 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 529 | INFOPLIST_KEY_WKWatchOnly = NO; 530 | IPHONEOS_DEPLOYMENT_TARGET = 15.6; 531 | LD_RUNPATH_SEARCH_PATHS = ( 532 | "$(inherited)", 533 | "@executable_path/Frameworks", 534 | ); 535 | MARKETING_VERSION = 2.1.4; 536 | PRODUCT_BUNDLE_IDENTIFIER = "ugritchina-icloud.com.QRCodeSwiftUI"; 537 | PRODUCT_NAME = "QR Generator"; 538 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 539 | SUPPORTS_MACCATALYST = NO; 540 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 541 | SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; 542 | SWIFT_EMIT_LOC_STRINGS = YES; 543 | SWIFT_VERSION = 5.0; 544 | TARGETED_DEVICE_FAMILY = 1; 545 | }; 546 | name = Release; 547 | }; 548 | /* End XCBuildConfiguration section */ 549 | 550 | /* Begin XCConfigurationList section */ 551 | 0E8732E628C8AE2C00645115 /* Build configuration list for PBXProject "QRCodeSwiftUI" */ = { 552 | isa = XCConfigurationList; 553 | buildConfigurations = ( 554 | 0E8732F728C8AE3100645115 /* Debug */, 555 | 0E8732F828C8AE3100645115 /* Release */, 556 | ); 557 | defaultConfigurationIsVisible = 0; 558 | defaultConfigurationName = Release; 559 | }; 560 | 0E8732F928C8AE3100645115 /* Build configuration list for PBXNativeTarget "QRCodeSwiftUI" */ = { 561 | isa = XCConfigurationList; 562 | buildConfigurations = ( 563 | 0E8732FA28C8AE3100645115 /* Debug */, 564 | 0E8732FB28C8AE3100645115 /* Release */, 565 | ); 566 | defaultConfigurationIsVisible = 0; 567 | defaultConfigurationName = Release; 568 | }; 569 | /* End XCConfigurationList section */ 570 | }; 571 | rootObject = 0E8732E328C8AE2C00645115 /* Project object */; 572 | } 573 | -------------------------------------------------------------------------------- /QRCodeSwiftUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /QRCodeSwiftUI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /QRCodeSwiftUI.xcodeproj/project.xcworkspace/xcuserdata/ulanagritcina.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI.xcodeproj/project.xcworkspace/xcuserdata/ulanagritcina.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /QRCodeSwiftUI.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI.xcodeproj/project.xcworkspace/xcuserdata/user.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /QRCodeSwiftUI.xcodeproj/xcuserdata/ulanagritcina.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /QRCodeSwiftUI.xcodeproj/xcuserdata/ulanagritcina.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | QRCodeSwiftUI.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /QRCodeSwiftUI.xcodeproj/xcuserdata/user.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | QRCodeSwiftUI.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/.DS_Store -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/Generate QR/GenerateQRView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct GenerateQRView: View { 4 | @StateObject var viewModel: ViewModel 5 | @Binding var editingQR: QRCode 6 | @Environment(\.dismiss) private var dismiss 7 | 8 | @StateObject private var photoPickerViewModel = PhotoPickerViewModel() 9 | 10 | init(editingQR: Binding, isEditingView: Bool = false) { 11 | let vm = ViewModel(editingQRCode: editingQR.wrappedValue, isEditView: isEditingView) 12 | _viewModel = StateObject(wrappedValue: vm) 13 | _editingQR = editingQR 14 | } 15 | 16 | var body: some View { 17 | NavigationView { 18 | ScrollView(showsIndicators: false) { 19 | VStack(spacing: 20) { 20 | qrNameView 21 | textEditor 22 | qrForeground 23 | Divider() 24 | qrBackground 25 | if viewModel.isFirstEnter { 26 | Text("Control the transparency of the color to adjust the background") 27 | .font(.footnote) 28 | .foregroundStyle(.secondary) 29 | .multilineTextAlignment(.center) 30 | } 31 | Divider() 32 | qrLogo 33 | 34 | } 35 | .padding(.horizontal) 36 | } 37 | .navigationTitle(viewModel.navigationTitle) 38 | .background(BackgroundView()) 39 | .overlay { generateButton } 40 | .onAppear { 41 | DispatchQueue.main.asyncAfter(deadline: .now() + 10) { 42 | withAnimation { 43 | viewModel.isFirstEnter = false 44 | } 45 | } 46 | } 47 | .toolbar { 48 | reset 49 | closeButton 50 | doneButtonForToolBar 51 | } 52 | .sheet(isPresented: $viewModel.isShowingQR, content: { 53 | GeneratedQRView(qrCode: viewModel.generatedQRCode) 54 | }) 55 | .sheet(isPresented: $viewModel.isShowPhotoPicker, onDismiss: { 56 | if viewModel.qrImageType == .background { 57 | viewModel.backgroundImageData = photoPickerViewModel.imageData 58 | } else { 59 | viewModel.logoImageData = photoPickerViewModel.imageData 60 | } 61 | }) { 62 | PhotoPickerView(vm: photoPickerViewModel) 63 | .ignoresSafeArea(edges: .bottom) 64 | } 65 | } 66 | } 67 | } 68 | 69 | struct ContentView_Previews: PreviewProvider { 70 | static var previews: some View { 71 | GenerateQRView(editingQR: .constant(QRCode())) 72 | } 73 | } 74 | 75 | //MARK: ELEMENTS 76 | 77 | extension GenerateQRView { 78 | 79 | @ViewBuilder private var qrPickerView: some View { 80 | if !viewModel.isEditView { 81 | HStack { 82 | Text("QR Type:") 83 | .font(.system(size: 18, weight: .regular, design: .rounded)) 84 | Spacer() 85 | qrPicker 86 | } 87 | .padding(.leading) 88 | .frame(height: 48) 89 | .background(Color.gray.opacity(0.25).cornerRadius(10).opacity(0.7)) 90 | } 91 | } 92 | 93 | @ViewBuilder private var qrPicker: some View { 94 | Picker(selection: $viewModel.qrType, label: Text("Picker")) { 95 | ForEach([QRType.text, QRType.wifi]) { type in 96 | Text(type.rawValue).tag(type) 97 | } 98 | } 99 | } 100 | 101 | @ViewBuilder private var qrNameView: some View { 102 | if viewModel.isEditView { 103 | TextField("title", text: $viewModel.qrCodeName) 104 | .appTextFieldStyle() 105 | } 106 | } 107 | 108 | private var textEditor: some View { 109 | VStack { 110 | if viewModel.isEditView { 111 | Text(viewModel.qrType.rawValue) 112 | .font(.headline) 113 | .foregroundStyle(.secondary) 114 | .frame(maxWidth: .infinity, alignment: .leading) 115 | } 116 | switch viewModel.qrType { 117 | case .text: 118 | qrTextEditor 119 | case .wifi: 120 | wifiQrCodeFields 121 | case .phone: 122 | phoneView 123 | default: 124 | Text("") 125 | } 126 | } 127 | .padding(.top) 128 | } 129 | 130 | private var qrForeground: some View { 131 | ColorPicker("Foreground", selection: $viewModel.foregroundColor) 132 | .font(.headline) 133 | } 134 | 135 | private var qrBackground: some View { 136 | HStack { 137 | ColorPicker("Background", selection: $viewModel.backgroundColor) 138 | .font(.headline) 139 | 140 | VStack { 141 | if let imageData = viewModel.backgroundImageData, 142 | let uiImage = UIImage(data: imageData){ 143 | Image(uiImage: uiImage) 144 | .resizable() 145 | .frame(width: 55, height: 55) 146 | .scaledToFit() 147 | .cornerRadius(10) 148 | 149 | } else { 150 | Rectangle() 151 | .frame(width: 55, height: 55) 152 | .cornerRadius(10) 153 | .foregroundStyle(.secondary.opacity(0.3)) 154 | .overlay { 155 | Image(systemName: "photo") 156 | .foregroundStyle(.gray) 157 | } 158 | } 159 | } 160 | .padding(.leading, 30) 161 | .onTapGesture { 162 | viewModel.qrImageType = .background 163 | viewModel.isShowPhotoPicker = true 164 | } 165 | if viewModel.backgroundImageData != nil { 166 | Button(action: { 167 | viewModel.backgroundImageData = nil 168 | }) { 169 | Image(systemName: "trash") 170 | .foregroundStyle(.red) 171 | } 172 | } 173 | 174 | } 175 | } 176 | 177 | private var qrLogo: some View { 178 | HStack { 179 | Text("Logo") 180 | .font(.headline) 181 | Spacer() 182 | VStack { 183 | if let imageData = viewModel.logoImageData, 184 | let uiImage = UIImage(data: imageData){ 185 | Image(uiImage: uiImage) 186 | .resizable() 187 | .frame(width: 55, height: 55) 188 | .scaledToFit() 189 | .cornerRadius(10) 190 | 191 | } else { 192 | Rectangle() 193 | .frame(width: 55, height: 55) 194 | .cornerRadius(10) 195 | .foregroundStyle(.secondary.opacity(0.3)) 196 | .overlay { 197 | Image(systemName: "photo") 198 | .foregroundStyle(.gray) 199 | } 200 | } 201 | } 202 | .padding(.leading, 30) 203 | .onTapGesture { 204 | viewModel.qrImageType = .logo 205 | viewModel.isShowPhotoPicker = true 206 | } 207 | if viewModel.logoImageData != nil { 208 | Button(action: { 209 | viewModel.logoImageData = nil 210 | }) { 211 | Image(systemName: "trash") 212 | .foregroundStyle(.red) 213 | } 214 | } 215 | } 216 | } 217 | 218 | private var qrTextEditor: some View { 219 | TextEditor(text: $viewModel.text) 220 | .frame(height: UIScreen.main.bounds.height / 5.5) 221 | .frame(maxWidth: 700) 222 | .cornerRadius(10) 223 | .overlay { 224 | RoundedRectangle(cornerRadius: 10) 225 | .stroke(.gray.opacity(0.4), lineWidth: 0.5) 226 | } 227 | } 228 | 229 | private var wifiQrCodeFields: some View { 230 | VStack(spacing: 15) { 231 | TextField("SSID", text: $viewModel.wifiSSID) 232 | .appTextFieldStyle() 233 | TextField("Password", text: $viewModel.wifiPassword) 234 | .appTextFieldStyle() 235 | } 236 | } 237 | 238 | private var phoneView: some View { 239 | TextField("phone number", text: $viewModel.phoneNumber) 240 | .appTextFieldStyle() 241 | .keyboardType(.numberPad) 242 | } 243 | 244 | private var colorPickers: some View { 245 | VStack(spacing: 30) { 246 | ColorPicker("Color", selection: $viewModel.foregroundColor) 247 | ColorPicker("Background color", selection: $viewModel.backgroundColor) 248 | Button(action: { viewModel.swapColors() }) { 249 | Text("Swap colors") 250 | } 251 | .frame(maxWidth: .infinity, alignment: .trailing) 252 | } 253 | .padding(.top) 254 | } 255 | 256 | private var generateButton: some View { 257 | VStack { 258 | Spacer() 259 | ButtonView( 260 | title: viewModel.generateButtonTitle, 261 | action: { 262 | viewModel.generateButtonTapped() 263 | if viewModel.isEditView { 264 | editingQR = viewModel.editingQRCode 265 | dismiss() 266 | } 267 | } 268 | ) 269 | .padding(.vertical, 8) 270 | .padding(.horizontal) 271 | .padding(.bottom, viewModel.isEditView 272 | ? UIScreen.main.bounds.height / 47 273 | : UIScreen.main.bounds.height / 10 274 | ) 275 | .background(.ultraThinMaterial) 276 | } 277 | .ignoresSafeArea() 278 | } 279 | 280 | private var doneButtonForToolBar: some ToolbarContent { 281 | ToolbarItem(placement: .keyboard) { 282 | Button("Done") { UIApplication.shared.endEditing() } 283 | .padding(.leading, UIScreen.main.bounds.width - 80) 284 | } 285 | } 286 | 287 | private var reset: some ToolbarContent { 288 | ToolbarItem(placement: .navigationBarLeading) { 289 | Button("Reset") { viewModel.reset() } 290 | } 291 | } 292 | 293 | private var closeButton: some ToolbarContent { 294 | ToolbarItem(placement: .navigationBarTrailing) { 295 | if viewModel.isEditView { 296 | Button(action: { dismiss() }) { 297 | Image(systemName: "xmark") 298 | } 299 | } else { 300 | qrPicker 301 | } 302 | } 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/Generate QR/GenerateQRViewModel.swift: -------------------------------------------------------------------------------- 1 | 2 | import SwiftUI 3 | 4 | 5 | enum QRImageType { 6 | case background 7 | case logo 8 | } 9 | 10 | extension GenerateQRView { 11 | 12 | enum QRType: String, CaseIterable, Identifiable { 13 | 14 | var id: String { 15 | switch self { 16 | case .text: 17 | return "text" 18 | case .wifi: 19 | return "wifi" 20 | default: 21 | return UUID().uuidString 22 | } 23 | } 24 | 25 | case text = "Link, email, some text" 26 | case wifi = "Wi-Fi" 27 | case phone = "Phone number" 28 | case massage = "Massage" 29 | } 30 | 31 | @MainActor final class ViewModel: ObservableObject { 32 | 33 | //MARK: - Published 34 | 35 | @Published var text = "" 36 | @Published var wifiSSID = "" 37 | @Published var wifiPassword = "" 38 | @Published var phoneNumber = "" 39 | @Published var foregroundColor: Color = .black 40 | @Published var backgroundColor: Color = .white 41 | @Published var backgroundImageData: Data? 42 | @Published var logoImageData: Data? 43 | @Published var qrCodeName = "" 44 | @Published var isShowingQR = false 45 | @Published var isShowPhotoPicker = false 46 | @Published var generatedQRCode: QRCode? 47 | @Published var editingQRCode: QRCode 48 | @Published var qrType: QRType = .text 49 | @Published var qrImageType: QRImageType = .background 50 | 51 | @AppStorage("isFirstEnter") var isFirstEnter: Bool = true 52 | 53 | // MARK: - Properties 54 | 55 | var isEditView: Bool 56 | var qrCodeImageData: Data? 57 | 58 | private let qrGenerator = QRGeneratorManager.shared 59 | 60 | init(editingQRCode: QRCode, isEditView: Bool) { 61 | self.editingQRCode = editingQRCode 62 | self.isEditView = isEditView 63 | setupEditingQrCode() 64 | qrCodeName = editingQRCode.name 65 | } 66 | 67 | // MARK: - Computed Properties 68 | 69 | var navigationTitle: String { 70 | isEditView ? "Edit" : "Qr" 71 | } 72 | 73 | var generateButtonTitle: String { 74 | isEditView ? "Update" : "Generate" 75 | } 76 | 77 | // MARK: - Private Methods 78 | 79 | private func generateQRCode() { 80 | let qrContent = switch qrType { 81 | case .text: text 82 | case .wifi: "WIFI:T:WPA;S:\(wifiSSID);P\(wifiPassword);;" 83 | case .phone: "tel:+\(phoneNumber)" 84 | default: 85 | "" 86 | } 87 | 88 | let logoImage = UIImage(data: logoImageData ?? Data()) 89 | let background = UIImage(data: backgroundImageData ?? Data()) 90 | 91 | if let data = qrGenerator.generateQRCode( 92 | background: backgroundColor, 93 | foregroundColor: foregroundColor, 94 | content: qrContent, 95 | overlayImage: logoImage, 96 | backgroundImage: background 97 | ) { 98 | switch qrType { 99 | case .text: 100 | generatedQRCode = QRCode( 101 | title: "", 102 | content: text, 103 | foregroundColor: RGBColor(color: foregroundColor), 104 | backgroundColor: RGBColor(color: backgroundColor), 105 | imageData: data, 106 | dateCreated: Date(), 107 | backgroundImageData: backgroundImageData, 108 | logoImageData: logoImageData, 109 | type: qrType.rawValue 110 | ) 111 | case .wifi: 112 | generatedQRCode = QRCode( 113 | title: "", 114 | content: "", 115 | foregroundColor: RGBColor(color: foregroundColor), 116 | backgroundColor: RGBColor(color: backgroundColor), 117 | imageData: data, 118 | dateCreated: Date(), 119 | backgroundImageData: backgroundImageData, 120 | logoImageData: logoImageData, 121 | type: qrType.rawValue, 122 | wifiSSID: wifiSSID, 123 | wifiPassword: wifiPassword 124 | ) 125 | case .phone: 126 | generatedQRCode = QRCode( 127 | title: "", 128 | content: "", 129 | foregroundColor: RGBColor(color: foregroundColor), 130 | backgroundColor: RGBColor(color: backgroundColor), 131 | imageData: data, 132 | dateCreated: Date(), 133 | backgroundImageData: backgroundImageData, 134 | logoImageData: logoImageData, 135 | type: qrType.rawValue, 136 | phoneNumber: phoneNumber 137 | ) 138 | default: 139 | break 140 | } 141 | } 142 | } 143 | 144 | // MARK: Editing QR-Code 145 | 146 | private func setupEditingQrCode() { 147 | if isEditView { 148 | text = editingQRCode.textContent 149 | setColorsForEditingQRCode() 150 | getEditingQRType() 151 | setEditingQRCodeContent() 152 | backgroundImageData = editingQRCode.backgroundImageData 153 | logoImageData = editingQRCode.logoImageData 154 | } 155 | } 156 | 157 | private func getEditingQRType() { 158 | for type in QRType.allCases { 159 | if type.rawValue == editingQRCode.type { 160 | qrType = type 161 | } 162 | } 163 | } 164 | 165 | func setEditingQRCodeContent() { 166 | switch qrType { 167 | case .text: 168 | text = editingQRCode.textContent 169 | case .wifi: 170 | wifiSSID = editingQRCode.wifiSSID ?? "" 171 | wifiPassword = editingQRCode.wifiPassword ?? "" 172 | case .phone: 173 | phoneNumber = editingQRCode.phoneNumber ?? "" 174 | default: 175 | break 176 | } 177 | } 178 | 179 | private func setColorsForEditingQRCode() { 180 | let foreground = editingQRCode.foregroundColor 181 | foregroundColor = Color( 182 | red: foreground.red, 183 | green: foreground.green, 184 | blue: foreground.blue, 185 | opacity: foreground.opacity 186 | ) 187 | let background = editingQRCode.backgroundColor 188 | backgroundColor = Color( 189 | red: background.red, 190 | green: background.green, 191 | blue: background.blue, 192 | opacity: background.opacity 193 | ) 194 | } 195 | 196 | // MARK: - Public Methods 197 | 198 | func generateButtonTapped() { 199 | generateQRCode() 200 | if isEditView { 201 | if let generatedQRCode { 202 | switch qrType { 203 | case .text: 204 | editingQRCode = QRCode( 205 | id: editingQRCode.id, 206 | title: qrCodeName, 207 | content: generatedQRCode.textContent, 208 | foregroundColor: generatedQRCode.foregroundColor, 209 | backgroundColor: generatedQRCode.backgroundColor, 210 | imageData: generatedQRCode.imageData, 211 | dateCreated: editingQRCode.dateCreated, 212 | backgroundImageData: generatedQRCode.backgroundImageData, 213 | logoImageData: generatedQRCode.logoImageData, 214 | type: qrType.rawValue 215 | ) 216 | case .wifi: 217 | editingQRCode = QRCode( 218 | id: editingQRCode.id, 219 | title: qrCodeName, 220 | content: "", 221 | foregroundColor: generatedQRCode.foregroundColor, 222 | backgroundColor: generatedQRCode.backgroundColor, 223 | imageData: generatedQRCode.imageData, 224 | dateCreated: editingQRCode.dateCreated, 225 | backgroundImageData: generatedQRCode.backgroundImageData, 226 | logoImageData: generatedQRCode.logoImageData, 227 | type: qrType.rawValue, 228 | wifiSSID: wifiSSID, 229 | wifiPassword: wifiPassword 230 | ) 231 | 232 | case .phone: 233 | editingQRCode = QRCode( 234 | id: editingQRCode.id, 235 | title: qrCodeName, 236 | content: "", 237 | foregroundColor: generatedQRCode.foregroundColor, 238 | backgroundColor: generatedQRCode.backgroundColor, 239 | imageData: generatedQRCode.imageData, 240 | dateCreated: editingQRCode.dateCreated, 241 | backgroundImageData: generatedQRCode.backgroundImageData, 242 | logoImageData: generatedQRCode.logoImageData, 243 | type: qrType.rawValue, 244 | phoneNumber: generatedQRCode.phoneNumber 245 | ) 246 | 247 | default: 248 | break 249 | } 250 | } 251 | } else { 252 | isShowingQR = true 253 | } 254 | } 255 | 256 | func reset() { 257 | switch qrType { 258 | case .text: 259 | text = "" 260 | case .wifi: 261 | wifiSSID = "" 262 | wifiPassword = "" 263 | 264 | case .phone: 265 | phoneNumber = "" 266 | default: break 267 | } 268 | foregroundColor = .black 269 | backgroundColor = .white 270 | backgroundImageData = nil 271 | logoImageData = nil 272 | } 273 | 274 | func swapColors() { 275 | let temporaryForegroundColor = foregroundColor 276 | foregroundColor = backgroundColor 277 | backgroundColor = temporaryForegroundColor 278 | } 279 | } 280 | 281 | } 282 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/Generate QR/Generated/GeneratedQRView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QRCodeView.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Ульяна Гритчина on 12.11.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct GeneratedQRView: View { 11 | let qrCode: QRCode? 12 | @StateObject private var vm = ViewModel() 13 | @Environment(\.dismiss) private var dismiss 14 | var body: some View { 15 | NavigationView { 16 | if let qrCode { 17 | ZStack { 18 | BackgroundView() 19 | qrCodeView 20 | saveButtonView 21 | } 22 | .navigationTitle("Generated") 23 | .alert("QR title", isPresented: $vm.isShowAlert) { 24 | TextField("title", text: $vm.qrTitle) 25 | .submitLabel(.done) 26 | Button("Cancel", role: .cancel) { } 27 | Button("Save", action: saveQR) 28 | } message: { 29 | Text("Set title for your QR code.") 30 | } 31 | .toolbar { 32 | ToolbarItem(placement: .topBarTrailing) { 33 | ShareQRButton(qrCode: qrCode) 34 | } 35 | } 36 | } 37 | } 38 | } 39 | } 40 | 41 | #Preview { 42 | GeneratedQRView( 43 | qrCode: QRCode( 44 | title: "name", 45 | content: "text", 46 | foregroundColor: RGBColor(color: .black), 47 | backgroundColor: RGBColor(color: .white), 48 | imageData: (UIImage(named: "defaultQRImage")?.pngData())!, 49 | dateCreated: Date(), 50 | type: "text" 51 | ) 52 | ) 53 | } 54 | 55 | extension GeneratedQRView { 56 | 57 | private var qrCodeView: some View { 58 | VStack { 59 | QrView(data: qrCode!.imageData, size: 300) 60 | Spacer() 61 | } 62 | .padding(.horizontal) 63 | .padding(.top) 64 | } 65 | 66 | private var saveButtonView: some View { 67 | VStack { 68 | Spacer() 69 | ButtonView(title: "Save", action: { vm.showAlert() }) 70 | .padding() 71 | .padding(.bottom, UIScreen.main.bounds.height / 49) 72 | } 73 | .ignoresSafeArea() 74 | } 75 | 76 | private func saveQR() { 77 | guard var qrCode else { return } 78 | qrCode.name = vm.qrTitle 79 | vm.addCode(qrCode) 80 | dismiss() 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/Generate QR/Generated/GeneratedQRViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GeneratedQRViewModel.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Ульяна Гритчина on 13.11.2023. 6 | // 7 | 8 | import Foundation 9 | 10 | extension GeneratedQRView { 11 | @MainActor final class ViewModel: ObservableObject { 12 | 13 | @Published var qrTitle = "" 14 | @Published var isShowAlert = false 15 | 16 | private let userDefaultsManager = UserDefaultsManager.shared 17 | var codes: [QRCode] = [] 18 | 19 | init() { 20 | setQRs() 21 | } 22 | 23 | private func setQRs() { 24 | userDefaultsManager.setSavedQrs(for: &codes) 25 | } 26 | 27 | func showAlert() { 28 | isShowAlert = true 29 | } 30 | 31 | func addCode(_ code: QRCode) { 32 | codes.append(code) 33 | userDefaultsManager.saveQrs(codes) 34 | } 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/SavedCodes/QRCodeDitail/QRCodeDetailView.swift: -------------------------------------------------------------------------------- 1 | 2 | import SwiftUI 3 | 4 | struct QRCodeDetailView: View { 5 | @ObservedObject private var viewModel: QRCodeDetailViewModel 6 | @Environment(\.dismiss) private var dismiss 7 | init(qrCode: QRCode) { 8 | viewModel = QRCodeDetailViewModel(qrCode: qrCode) 9 | } 10 | 11 | var body: some View { 12 | ZStack { 13 | BackgroundView() 14 | VStack { 15 | Spacer() 16 | QrView(data: viewModel.qrCode.imageData, size: 300) 17 | Spacer() 18 | Spacer() 19 | buttons 20 | } 21 | } 22 | .navigationTitle(viewModel.qrCode.name) 23 | .toolbar { 24 | ToolbarItem(placement: .topBarTrailing) { 25 | ShareQRButton(qrCode: viewModel.qrCode) 26 | } 27 | } 28 | .sheet(isPresented: $viewModel.isShowEditView, content: { 29 | GenerateQRView(editingQR: $viewModel.qrCode, isEditingView: true) 30 | }) 31 | .onChange(of: viewModel.qrCode) { _ in 32 | viewModel.updateQRInUserDefaults() 33 | } 34 | .alert(viewModel.deleteAlertTitel, isPresented: $viewModel.isShowAlert) { 35 | Button("Cancel", role: .cancel) { } 36 | Button("Delete", role: .destructive) { 37 | viewModel.deleteQRCode() 38 | dismiss() 39 | } 40 | } 41 | } 42 | 43 | } 44 | 45 | struct QRCodeDetailView_Previews: PreviewProvider { 46 | static var previews: some View { 47 | NavigationView { 48 | QRCodeDetailView( 49 | qrCode: QRCode( 50 | title: "name", 51 | content: "https://www.apple.com", 52 | foregroundColor: RGBColor(color: .red), 53 | backgroundColor: RGBColor(color: .green), 54 | imageData: (UIImage(named: "defaultQRImage")?.pngData())!, 55 | dateCreated: Date(), 56 | type: "text" 57 | ) 58 | ) 59 | } 60 | } 61 | } 62 | 63 | extension QRCodeDetailView { 64 | 65 | private var buttons: some View { 66 | HStack(spacing: .zero) { 67 | deleteButton 68 | editButton 69 | brightButton 70 | browserButton 71 | } 72 | .padding() 73 | .padding(.bottom) 74 | } 75 | 76 | private var deleteButton: some View { 77 | Button(action: viewModel.deleteButtonDidTapp) { 78 | Image(systemName: "trash") 79 | .circleModifier() 80 | .padding() 81 | } 82 | } 83 | 84 | private var editButton: some View { 85 | Button(action: viewModel.showEditView) { 86 | Image(systemName: "slider.horizontal.3") 87 | .circleModifier() 88 | .padding() 89 | } 90 | } 91 | 92 | private var brightButton: some View { 93 | Button(action: { 94 | viewModel.didTapBrightButton() 95 | UIScreen.main.brightness = CGFloat(viewModel.isLightOn ? 1 : 0.5) 96 | }, label: { 97 | Image(systemName: viewModel.brightButtonImageName) 98 | .circleModifier() 99 | .padding() 100 | }) 101 | } 102 | 103 | @ViewBuilder private var browserButton: some View { 104 | if let url = URL(string: viewModel.qrCode.textContent) { 105 | if UIApplication.shared.canOpenURL(url) { 106 | Link(destination: url, label: { 107 | Image(systemName: "link") 108 | .circleModifier() 109 | .padding() 110 | }) 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/SavedCodes/QRCodeDitail/QRCodeDetailViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QRCodeDetailViewModel.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Uliana Gritchina on 15.11.2023. 6 | // 7 | 8 | import Foundation 9 | 10 | @MainActor final class QRCodeDetailViewModel: ObservableObject { 11 | 12 | private var savedQrs: [QRCode] = [] 13 | private let userDefaultsManager = UserDefaultsManager.shared 14 | 15 | @Published var isLightOn = false 16 | @Published var isShowEditView = false 17 | @Published var isShowAlert = false 18 | 19 | var qrCode: QRCode 20 | 21 | init(qrCode: QRCode) { 22 | self.qrCode = qrCode 23 | userDefaultsManager.setSavedQrs(for: &savedQrs) 24 | } 25 | 26 | var deleteAlertTitel: String { 27 | "Are you sure you want to delete QR" 28 | + 29 | " '\(qrCode.name)'" 30 | } 31 | 32 | var brightButtonImageName: String { 33 | isLightOn ? "sun.max" : "sun.min" 34 | } 35 | 36 | var qrCodeImageData: Data { 37 | qrCode.imageData 38 | } 39 | 40 | func deleteButtonDidTapp() { 41 | isShowAlert.toggle() 42 | } 43 | 44 | func deleteQRCode() { 45 | savedQrs.removeAll(where: { $0.id == qrCode.id }) 46 | userDefaultsManager.saveQrs(savedQrs) 47 | } 48 | 49 | func didTapBrightButton() { 50 | isLightOn.toggle() 51 | } 52 | 53 | func showEditView() { 54 | isShowEditView = true 55 | } 56 | 57 | func updateQRInUserDefaults() { 58 | savedQrs.removeAll(where: {$0.id == qrCode.id }) 59 | savedQrs.append(qrCode) 60 | userDefaultsManager.saveQrs(savedQrs) 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/SavedCodes/SavedCodeRowView.swift: -------------------------------------------------------------------------------- 1 | 2 | import SwiftUI 3 | 4 | struct SavedCodeRowView: View { 5 | let code: QRCode 6 | var body: some View { 7 | VStack { 8 | VStack(alignment: .leading) { 9 | qrCodeName 10 | HStack(alignment: .top) { 11 | qrCodeImage 12 | qrCodeData 13 | Spacer() 14 | } 15 | } 16 | } 17 | .padding() 18 | .background(Color("cardBackground")) 19 | .cornerRadius(10) 20 | .shadow(color: Color("shadow").opacity(0.5), radius: 5, x: 3, y: 5) 21 | } 22 | } 23 | 24 | struct SavedCodeRowView_Previews: PreviewProvider { 25 | static var previews: some View { 26 | SavedCodeRowView( 27 | code: QRCode( 28 | title: "name", 29 | content: "text", 30 | foregroundColor: RGBColor(color: .black), 31 | backgroundColor: RGBColor(color: .white), 32 | imageData: (UIImage(named: "defaultQRImage")?.pngData())!, 33 | dateCreated: Date(), 34 | type: "text" 35 | ) 36 | ) 37 | } 38 | } 39 | 40 | extension SavedCodeRowView { 41 | 42 | private var qrCodeName: some View { 43 | Text(code.name) 44 | .font(.headline) 45 | } 46 | 47 | private var qrCodeImage: some View { 48 | Image(uiImage: UIImage(data: code.imageData)!) 49 | .interpolation(.none) 50 | .resizable() 51 | .frame(width: 100, height: 100) 52 | .cornerRadius(5) 53 | .shadow(color: .black.opacity(0.2), radius: 5, x: 0, y: 0) 54 | } 55 | 56 | private var qrCodeData: some View { 57 | Text(code.textContent) 58 | .font(.subheadline) 59 | .foregroundColor(.gray) 60 | .multilineTextAlignment(.leading) 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/SavedCodes/SavedCodesView.swift: -------------------------------------------------------------------------------- 1 | 2 | import SwiftUI 3 | 4 | struct SavedCodesView: View { 5 | @EnvironmentObject var vm: SavedCodesViewViewModel 6 | var body: some View { 7 | NavigationView { 8 | ZStack { 9 | BackgroundView() 10 | ScrollView { 11 | if !vm.codes.isEmpty { 12 | qrsList 13 | } else { 14 | Text("No saved QR codes yet") 15 | .bold() 16 | } 17 | } 18 | } 19 | .navigationTitle("Saved") 20 | .onAppear { vm.setQRs() } 21 | } 22 | .navigationViewStyle(.stack) 23 | } 24 | 25 | private var qrsList: some View { 26 | VStack { 27 | ForEach(vm.codes) { code in 28 | NavigationLink(destination: QRCodeDetailView(qrCode: code)) { 29 | SavedCodeRowView(code: code) 30 | .padding(.horizontal) 31 | .padding(.bottom) 32 | } 33 | } 34 | } 35 | } 36 | 37 | } 38 | 39 | struct SavedCodesView_Previews: PreviewProvider { 40 | static var previews: some View { 41 | SavedCodesView() 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/SavedCodes/SavedCodesViewModel.swift: -------------------------------------------------------------------------------- 1 | 2 | import Foundation 3 | 4 | class SavedCodesViewViewModel: ObservableObject { 5 | 6 | @Published var codes: [QRCode] = [] 7 | 8 | private let userDefaultsManager = UserDefaultsManager.shared 9 | 10 | init() { 11 | setQRs() 12 | } 13 | 14 | func setQRs() { 15 | userDefaultsManager.setSavedQrs(for: &codes) 16 | codes = codes.sorted(by: { $0.dateCreated > $1.dateCreated}) 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/Settings/SettingsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InfoView.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Ульяна Гритчина on 15.11.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SettingsView: View { 11 | @StateObject private var viewModel = ViewModel() 12 | var body: some View { 13 | NavigationView { 14 | ZStack { 15 | BackgroundView() 16 | ScrollView { 17 | VStack(spacing: 30) { 18 | text 19 | donatesList 20 | removeAddsButton 21 | appStoreButtons 22 | } 23 | .padding() 24 | } 25 | } 26 | .navigationTitle("Settings") 27 | } 28 | } 29 | } 30 | 31 | #Preview { 32 | SettingsView() 33 | } 34 | 35 | extension SettingsView { 36 | 37 | private var text: some View { 38 | Text("If you like the app you can support the developer.") 39 | .multilineTextAlignment(.center) 40 | .font(.headline) 41 | } 42 | 43 | private var donatesList: some View { 44 | VStack { 45 | ForEach(viewModel.prices, id: \.self) { price in 46 | donateCell(price: price, action: {}) 47 | } 48 | } 49 | } 50 | 51 | private var removeAddsButton: some View { 52 | Button(action: { RequestReviewManager.shared.showReviewView() }, label: { 53 | Text("Remove adds for $ 7") 54 | .font(.headline) 55 | .foregroundStyle(.white) 56 | .font(.headline) 57 | .frame(height: 45) 58 | .frame(maxWidth: 700) 59 | .background(.blue) 60 | .cornerRadius(10) 61 | }) 62 | } 63 | 64 | private var appStoreButtons: some View { 65 | HStack(spacing: 15) { 66 | rateTheAppButton 67 | writeReviewLink 68 | } 69 | } 70 | 71 | private var rateTheAppButton: some View { 72 | Button(action: { RequestReviewManager.shared.showReviewView() }, label: { 73 | Text("Rate the app") 74 | .font(.headline) 75 | .foregroundStyle(.white) 76 | .font(.headline) 77 | .frame(height: 45) 78 | .frame(maxWidth: 700) 79 | .background(.blue) 80 | .cornerRadius(10) 81 | }) 82 | } 83 | 84 | private var writeReviewLink: some View { 85 | Link(destination: viewModel.writeReviewURL) { 86 | Text("Write a review") 87 | .font(.headline) 88 | .foregroundStyle(.white) 89 | .font(.headline) 90 | .frame(height: 45) 91 | .frame(maxWidth: 700) 92 | .background(.blue) 93 | .cornerRadius(10) 94 | } 95 | } 96 | 97 | private func donateCell( 98 | price: String, 99 | action: @escaping () -> () 100 | ) -> some View { 101 | Button(action: action, label: { 102 | HStack { 103 | Text(price) 104 | Spacer() 105 | Image(systemName: "chevron.right") 106 | } 107 | .padding() 108 | .background(Color("cardBackground")) 109 | .background(.ultraThinMaterial) 110 | .cornerRadius(10) 111 | 112 | }) 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/Settings/SettingsViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsViewModel.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Ульяна Гритчина on 21.11.2023. 6 | // 7 | 8 | import Foundation 9 | 10 | extension SettingsView { 11 | 12 | @MainActor final class ViewModel: ObservableObject { 13 | 14 | let prices = ["$ 0.99", "$ 4.99", "$ 9.99", "$ 100"] 15 | let writeReviewURL = URL( 16 | string: "https://apps.apple.com/ru/app/my-qr/id1644582305?action=write-review" 17 | )! 18 | 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Core/TabView/TabViewView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabViewView.swift 3 | // WordsAndCards 4 | // 5 | // Created by Ульяна Гритчина on 09.05.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TabViewView: View { 11 | var body: some View { 12 | TabView { 13 | GenerateQRView(editingQR: .constant(QRCode())) 14 | .tabItem { 15 | Label("Generate QR", systemImage: "qrcode") 16 | } 17 | 18 | SavedCodesView() 19 | .tabItem { 20 | Label("Saved", systemImage: "star.square") 21 | } 22 | // SettingsView() 23 | // .tabItem { 24 | // Label("Settings", systemImage: "gear") 25 | // } 26 | } 27 | } 28 | } 29 | 30 | struct TabViewView_Previews: PreviewProvider { 31 | static var previews: some View { 32 | TabViewView() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/DesignSystem/BackgroundView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BackgroundView.swift 3 | // WordsAndCards 4 | // 5 | // Created by Ульяна Гритчина on 21.02.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BackgroundView: View { 11 | var body: some View { 12 | Color("background").ignoresSafeArea() 13 | } 14 | } 15 | 16 | struct BackgroundView_Previews: PreviewProvider { 17 | static var previews: some View { 18 | BackgroundView() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/DesignSystem/ButtonView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct ButtonView: View { 4 | let title: String 5 | let action: () -> () 6 | var body: some View { 7 | Button(action: action) { 8 | Text(title) 9 | .font(.headline) 10 | .frame(maxWidth: .infinity) 11 | .frame(height: 50) 12 | .foregroundColor(.textColor) 13 | .background(Color.accentColor) 14 | .cornerRadius(10) 15 | } 16 | } 17 | } 18 | 19 | struct ButtonView_Previews: PreviewProvider { 20 | static var previews: some View { 21 | ButtonView(title: "title", action: {}) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/DesignSystem/PhotoPickerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoPicker.swift 3 | // Test 4 | // 5 | // Created by Ульяна Гритчина on 12.04.2022. 6 | // 7 | 8 | import SwiftUI 9 | 10 | final class PhotoPickerViewModel: ObservableObject { 11 | @Published var imageData: Data? 12 | } 13 | 14 | struct PhotoPickerView: UIViewControllerRepresentable { 15 | let vm: PhotoPickerViewModel 16 | 17 | func makeUIViewController(context: Context) -> UIImagePickerController { 18 | let picker = UIImagePickerController() 19 | picker.delegate = context.coordinator 20 | picker.allowsEditing = true 21 | return picker 22 | } 23 | 24 | func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) { } 25 | 26 | func makeCoordinator() -> Coordinator { 27 | return Coordinator(photoPicker: self, vm: vm) 28 | } 29 | 30 | final class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate { 31 | 32 | let photoPicker: PhotoPickerView 33 | let vm: PhotoPickerViewModel 34 | 35 | init(photoPicker: PhotoPickerView, vm: PhotoPickerViewModel) { 36 | self.photoPicker = photoPicker 37 | self.vm = vm 38 | } 39 | 40 | func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { 41 | if let image = info[.editedImage] as? UIImage { 42 | guard let data = image.pngData() else { 43 | return 44 | } 45 | vm.imageData = data 46 | 47 | } else { 48 | 49 | } 50 | picker.dismiss(animated: true) 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/DesignSystem/QrView.swift: -------------------------------------------------------------------------------- 1 | 2 | import SwiftUI 3 | 4 | struct QrView: View { 5 | let data: Data 6 | let size: CGFloat 7 | 8 | init(data: Data, size: CGFloat = 200) { 9 | self.data = data 10 | self.size = size 11 | } 12 | 13 | var body: some View { 14 | Image(uiImage: UIImage(data: data)!) 15 | .interpolation(.none) 16 | .resizable() 17 | .scaledToFit() 18 | .frame(maxWidth: size, maxHeight: size) 19 | .clipShape(RoundedRectangle(cornerRadius: 5)) 20 | .shadow(radius: 5) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/DesignSystem/ShareQRButton.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct ShareQRButton: View { 4 | let qrCode: QRCode 5 | var body: some View { 6 | if #available(iOS 16.0, *) { 7 | shareLink 8 | } else { 9 | shareButton 10 | } 11 | } 12 | } 13 | 14 | struct ShareButtonView_Previews: PreviewProvider { 15 | static var previews: some View { 16 | ShareQRButton( 17 | qrCode: QRCode( 18 | title: "", 19 | content: "", 20 | foregroundColor: RGBColor(color: .black), 21 | backgroundColor: RGBColor(color: .white), 22 | imageData: Data(), 23 | dateCreated: Date(), 24 | type: "text" 25 | ) 26 | ) 27 | } 28 | } 29 | 30 | extension ShareQRButton { 31 | 32 | private var shareButton: some View { 33 | Button(action: { showShareView() }) { 34 | Image(systemName: "square.and.arrow.up") 35 | .font(.system(size: 18)) 36 | } 37 | } 38 | 39 | @ViewBuilder private var shareLink: some View { 40 | if #available(iOS 16.0, *) { 41 | ShareLink( 42 | item: 43 | Image(uiImage: (UIImage(data: qrCode.imageData) 44 | ?? UIImage(named: "defaultQRImage"))!), 45 | preview: 46 | SharePreview( 47 | "QR-code - \(qrCode.name)", 48 | image: 49 | Image(uiImage: (UIImage(data: qrCode.imageData) 50 | ?? UIImage(named: "defaultQRImage"))!))) { 51 | Image(systemName: "square.and.arrow.up") 52 | .font(.system(size: 18)) 53 | } 54 | } 55 | } 56 | 57 | private func showShareView() { 58 | let activityVC = UIActivityViewController( 59 | activityItems: [qrCode.imageData], 60 | applicationActivities: nil 61 | ) 62 | let scenes = UIApplication.shared.connectedScenes 63 | let windowScene = scenes.first as? UIWindowScene 64 | let window = windowScene?.windows.first 65 | let vc = window?.rootViewController 66 | activityVC.popoverPresentationController?.sourceView = vc?.view 67 | activityVC.popoverPresentationController?.sourceRect = .zero 68 | window?.rootViewController?.present( 69 | activityVC, animated: true, completion: nil 70 | ) 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/DesignSystem/ViewModifires/AppTextFieldStyle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppTextFieldStile.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Ульяна Гритчина on 24.11.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct AppTextFieldStyle: ViewModifier { 11 | 12 | func body(content: Content) -> some View { 13 | content 14 | .font(.system( 15 | size: 20, 16 | weight: .regular, design: .rounded 17 | )) 18 | .padding(10) 19 | .background(.gray.opacity(0.2)) 20 | .cornerRadius(8) 21 | .frame(maxWidth: 700) 22 | } 23 | } 24 | 25 | extension View { 26 | func appTextFieldStyle() -> some View { 27 | modifier(AppTextFieldStyle()) 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/DesignSystem/ViewModifires/CircleModifier.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircleModifier.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Ульяна Гритчина on 20.01.2024. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CircleModifier: ViewModifier { 11 | func body(content: Content) -> some View { 12 | content 13 | .frame(width: 50, height: 50) 14 | .background(Color("cardBackground")) 15 | .clipShape(.circle) 16 | .shadow(color: .black.opacity(0.2), radius: 5, x: 0, y: 0) 17 | } 18 | } 19 | 20 | extension View { 21 | func circleModifier() -> some View { 22 | modifier(CircleModifier()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ITSAppUsesNonExemptEncryption 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Managers/QRGeneratorManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QRGeneratorManager.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Ульяна Гритчина on 12.11.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | final class QRGeneratorManager { 11 | static let shared = QRGeneratorManager() 12 | private init() { } 13 | 14 | func generateQRCode(background: Color = .white, foregroundColor: Color = .black, content: String) -> Data? { 15 | var qrCodeImageData: Data? 16 | let backgroundColor = UIColor(background) 17 | let foregroundColor = UIColor(foregroundColor) 18 | let data = content.data(using: String.Encoding.utf8) 19 | if let filter = CIFilter(name: "CIQRCodeGenerator") { 20 | guard let colorFilter = CIFilter(name: "CIFalseColor") else { return nil } 21 | filter.setValue(data, forKey: "inputMessage") 22 | // filter.setValue("H", forKey: "inputCorrectionLevel") 23 | colorFilter.setValue(filter.outputImage, forKey: "inputImage") 24 | colorFilter.setValue(CIColor(color: backgroundColor), forKey: "inputColor1") // Background 25 | colorFilter.setValue(CIColor(color: foregroundColor), forKey: "inputColor0") // Foreground 26 | guard let outputImage = colorFilter.outputImage else { return nil } 27 | let transform = CGAffineTransform(scaleX: 20, y: 20) 28 | let scaledCIImage = outputImage.transformed(by: transform) 29 | 30 | qrCodeImageData = UIImage(ciImage: scaledCIImage).pngData() 31 | } 32 | return qrCodeImageData 33 | } 34 | 35 | func generateQRCode(background: Color = .white, foregroundColor: Color = .black, content: String, overlayImage: UIImage? = nil, backgroundImage: UIImage? = nil) -> Data? { 36 | var qrCodeImageData: Data? 37 | let backgroundColor = UIColor(background) 38 | let foregroundColor = UIColor(foregroundColor) 39 | let data = content.data(using: String.Encoding.utf8) 40 | 41 | if let filter = CIFilter(name: "CIQRCodeGenerator") { 42 | guard let colorFilter = CIFilter(name: "CIFalseColor") else { return nil } 43 | filter.setValue(data, forKey: "inputMessage") 44 | colorFilter.setValue(filter.outputImage, forKey: "inputImage") 45 | colorFilter.setValue(CIColor(color: backgroundColor), forKey: "inputColor1") // Background 46 | colorFilter.setValue(CIColor(color: foregroundColor), forKey: "inputColor0") // Foreground 47 | 48 | guard let outputImage = colorFilter.outputImage else { return nil } 49 | let transform = CGAffineTransform(scaleX: 20, y: 20) 50 | let scaledCIImage = outputImage.transformed(by: transform) 51 | 52 | // Создаем UIImage из CIImage 53 | let qrCodeImage = UIImage(ciImage: scaledCIImage) 54 | 55 | // Начинаем графический контекст 56 | UIGraphicsBeginImageContext(qrCodeImage.size) 57 | 58 | // Рисуем фоновое изображение, если оно предоставлено 59 | if let backgroundImage = backgroundImage { 60 | backgroundImage.draw(in: CGRect(origin: .zero, size: CGSize(width: qrCodeImage.size.width + 20, height: qrCodeImage.size.height + 20))) 61 | } else { 62 | // Если фон не задан, рисуем цветной фон 63 | backgroundColor.setFill() 64 | UIRectFill(CGRect(origin: .zero, size: qrCodeImage.size)) 65 | } 66 | 67 | // Рисуем QR-код 68 | qrCodeImage.draw(in: CGRect(origin: .zero, size: qrCodeImage.size)) 69 | 70 | // Если есть изображение для наложения, добавляем его 71 | if let overlayImage = overlayImage { 72 | print(overlayImage) 73 | // Определяем размер и позицию наложенного изображения 74 | let overlaySize = CGSize(width: qrCodeImage.size.width / 5, height: qrCodeImage.size.height / 5) // Пример размера 75 | let overlayOrigin = CGPoint(x: (qrCodeImage.size.width - overlaySize.width) / 2, 76 | y: (qrCodeImage.size.height - overlaySize.height) / 2) // Центрируем наложенное изображение 77 | 78 | let rect = CGRect(origin: overlayOrigin, size: overlaySize) 79 | UIBezierPath(roundedRect: rect, cornerRadius: 10).addClip() 80 | overlayImage.draw(in: rect) 81 | } 82 | 83 | // Получаем итоговое изображение 84 | let finalImage = UIGraphicsGetImageFromCurrentImageContext() 85 | UIGraphicsEndImageContext() 86 | 87 | qrCodeImageData = finalImage?.pngData() 88 | } 89 | 90 | return qrCodeImageData 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Managers/RequestReviewManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RequestReviewManager.swift 3 | // WordsAndCards 4 | // 5 | // Created by Ульяна Гритчина on 04.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | import StoreKit 10 | 11 | class RequestReviewManager { 12 | static let shared = RequestReviewManager() 13 | 14 | func showReviewView() { 15 | if let scene = UIApplication.shared.connectedScenes.first(where: {$0.activationState == .foregroundActive}) as? UIWindowScene { 16 | SKStoreReviewController.requestReview(in: scene) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Managers/UserDefaultsManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SabedQRCodesManager.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Ульяна Гритчина on 13.11.2023. 6 | // 7 | 8 | import Foundation 9 | 10 | final class UserDefaultsManager { 11 | static let shared = UserDefaultsManager() 12 | private init() { } 13 | 14 | let codesKey: String = "codes_list" 15 | 16 | func saveQrs(_ codes: [QRCode]) { 17 | if let encodedData = try? JSONEncoder().encode(codes) { 18 | UserDefaults.standard.set(encodedData, forKey: codesKey) 19 | } 20 | } 21 | 22 | func setSavedQrs(for codes: inout [QRCode]) { 23 | guard 24 | let data = UserDefaults.standard.data(forKey: codesKey), 25 | let savedCodes = try? JSONDecoder().decode([QRCode].self, from: data) 26 | else { return } 27 | 28 | codes = savedCodes 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Models/QRCode.swift: -------------------------------------------------------------------------------- 1 | 2 | import SwiftUI 3 | 4 | struct QRCode: Identifiable, Codable, Equatable { 5 | 6 | var id = UUID().uuidString 7 | var name: String 8 | let textContent: String 9 | let foregroundColor: RGBColor 10 | let backgroundColor: RGBColor 11 | let imageData: Data 12 | let dateCreated: Date 13 | let backgroundImageData: Data? 14 | let logoImageData: Data? 15 | let type: String? 16 | let wifiSSID: String? 17 | let wifiPassword: String? 18 | let phoneNumber: String? 19 | 20 | init( 21 | id: String = UUID().uuidString, 22 | title: String, 23 | content: String, 24 | foregroundColor: RGBColor, 25 | backgroundColor: RGBColor, 26 | imageData: Data, 27 | dateCreated: Date, 28 | backgroundImageData: Data? = nil, 29 | logoImageData: Data? = nil, 30 | type: String?, 31 | wifiSSID: String? = nil, 32 | wifiPassword: String? = nil, 33 | phoneNumber: String? = nil 34 | ) { 35 | self.id = id 36 | self.name = title 37 | self.textContent = content 38 | self.foregroundColor = foregroundColor 39 | self.backgroundColor = backgroundColor 40 | self.imageData = imageData 41 | self.dateCreated = dateCreated 42 | self.type = type 43 | self.backgroundImageData = backgroundImageData 44 | self.logoImageData = logoImageData 45 | self.wifiSSID = wifiSSID 46 | self.wifiPassword = wifiPassword 47 | self.phoneNumber = phoneNumber 48 | } 49 | 50 | init() { 51 | name = "" 52 | textContent = "" 53 | foregroundColor = RGBColor(color: .black) 54 | backgroundColor = RGBColor(color: .white) 55 | imageData = Data() 56 | dateCreated = Date() 57 | type = "Link, email, some text" 58 | backgroundImageData = nil 59 | logoImageData = nil 60 | wifiSSID = nil 61 | wifiPassword = nil 62 | phoneNumber = nil 63 | } 64 | 65 | static func == (lhs: QRCode, rhs: QRCode) -> Bool { 66 | if lhs.id == rhs.id, 67 | lhs.name == rhs.name, 68 | lhs.textContent == rhs.textContent, 69 | lhs.wifiSSID == rhs.wifiSSID, 70 | lhs.wifiPassword == rhs.wifiPassword, 71 | lhs.type == rhs.type, 72 | lhs.imageData == rhs.imageData { 73 | return true 74 | } else { 75 | return false 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/Models/RGBColor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RGBColor.swift 3 | // QRCodeSwiftUI 4 | // 5 | // Created by Uliana Gritchina on 20.11.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct RGBColor: Codable { 11 | var red: Double = 1 12 | var green: Double = 1 13 | var blue: Double = 1 14 | var opacity: Double = 1 15 | 16 | init(color: Color) { 17 | guard let components = color.cgColor?.components else { return } 18 | red = components[0] 19 | green = components[1] 20 | blue = components[2] 21 | opacity = components[3] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/.DS_Store -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "platform" : "universal", 6 | "reference" : "labelColor" 7 | }, 8 | "idiom" : "universal" 9 | } 10 | ], 11 | "info" : { 12 | "author" : "xcode", 13 | "version" : 1 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/128.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/16.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/172.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/172.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/196.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/216.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/256.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/32.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/48.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/512.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/55.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/64.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/88.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "40.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "60.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "29.png", 17 | "idiom" : "iphone", 18 | "scale" : "1x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "58.png", 23 | "idiom" : "iphone", 24 | "scale" : "2x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "87.png", 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "29x29" 32 | }, 33 | { 34 | "filename" : "80.png", 35 | "idiom" : "iphone", 36 | "scale" : "2x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "120.png", 41 | "idiom" : "iphone", 42 | "scale" : "3x", 43 | "size" : "40x40" 44 | }, 45 | { 46 | "filename" : "57.png", 47 | "idiom" : "iphone", 48 | "scale" : "1x", 49 | "size" : "57x57" 50 | }, 51 | { 52 | "filename" : "114.png", 53 | "idiom" : "iphone", 54 | "scale" : "2x", 55 | "size" : "57x57" 56 | }, 57 | { 58 | "filename" : "120.png", 59 | "idiom" : "iphone", 60 | "scale" : "2x", 61 | "size" : "60x60" 62 | }, 63 | { 64 | "filename" : "180.png", 65 | "idiom" : "iphone", 66 | "scale" : "3x", 67 | "size" : "60x60" 68 | }, 69 | { 70 | "filename" : "20.png", 71 | "idiom" : "ipad", 72 | "scale" : "1x", 73 | "size" : "20x20" 74 | }, 75 | { 76 | "filename" : "40.png", 77 | "idiom" : "ipad", 78 | "scale" : "2x", 79 | "size" : "20x20" 80 | }, 81 | { 82 | "filename" : "29.png", 83 | "idiom" : "ipad", 84 | "scale" : "1x", 85 | "size" : "29x29" 86 | }, 87 | { 88 | "filename" : "58.png", 89 | "idiom" : "ipad", 90 | "scale" : "2x", 91 | "size" : "29x29" 92 | }, 93 | { 94 | "filename" : "40.png", 95 | "idiom" : "ipad", 96 | "scale" : "1x", 97 | "size" : "40x40" 98 | }, 99 | { 100 | "filename" : "80.png", 101 | "idiom" : "ipad", 102 | "scale" : "2x", 103 | "size" : "40x40" 104 | }, 105 | { 106 | "filename" : "50.png", 107 | "idiom" : "ipad", 108 | "scale" : "1x", 109 | "size" : "50x50" 110 | }, 111 | { 112 | "filename" : "100.png", 113 | "idiom" : "ipad", 114 | "scale" : "2x", 115 | "size" : "50x50" 116 | }, 117 | { 118 | "filename" : "72.png", 119 | "idiom" : "ipad", 120 | "scale" : "1x", 121 | "size" : "72x72" 122 | }, 123 | { 124 | "filename" : "144.png", 125 | "idiom" : "ipad", 126 | "scale" : "2x", 127 | "size" : "72x72" 128 | }, 129 | { 130 | "filename" : "76.png", 131 | "idiom" : "ipad", 132 | "scale" : "1x", 133 | "size" : "76x76" 134 | }, 135 | { 136 | "filename" : "152.png", 137 | "idiom" : "ipad", 138 | "scale" : "2x", 139 | "size" : "76x76" 140 | }, 141 | { 142 | "filename" : "167.png", 143 | "idiom" : "ipad", 144 | "scale" : "2x", 145 | "size" : "83.5x83.5" 146 | }, 147 | { 148 | "filename" : "1024.png", 149 | "idiom" : "ios-marketing", 150 | "scale" : "1x", 151 | "size" : "1024x1024" 152 | }, 153 | { 154 | "filename" : "16.png", 155 | "idiom" : "mac", 156 | "scale" : "1x", 157 | "size" : "16x16" 158 | }, 159 | { 160 | "filename" : "32.png", 161 | "idiom" : "mac", 162 | "scale" : "2x", 163 | "size" : "16x16" 164 | }, 165 | { 166 | "filename" : "32.png", 167 | "idiom" : "mac", 168 | "scale" : "1x", 169 | "size" : "32x32" 170 | }, 171 | { 172 | "filename" : "64.png", 173 | "idiom" : "mac", 174 | "scale" : "2x", 175 | "size" : "32x32" 176 | }, 177 | { 178 | "filename" : "128.png", 179 | "idiom" : "mac", 180 | "scale" : "1x", 181 | "size" : "128x128" 182 | }, 183 | { 184 | "filename" : "256.png", 185 | "idiom" : "mac", 186 | "scale" : "2x", 187 | "size" : "128x128" 188 | }, 189 | { 190 | "filename" : "256.png", 191 | "idiom" : "mac", 192 | "scale" : "1x", 193 | "size" : "256x256" 194 | }, 195 | { 196 | "filename" : "512.png", 197 | "idiom" : "mac", 198 | "scale" : "2x", 199 | "size" : "256x256" 200 | }, 201 | { 202 | "filename" : "512.png", 203 | "idiom" : "mac", 204 | "scale" : "1x", 205 | "size" : "512x512" 206 | }, 207 | { 208 | "filename" : "1024.png", 209 | "idiom" : "mac", 210 | "scale" : "2x", 211 | "size" : "512x512" 212 | }, 213 | { 214 | "filename" : "48.png", 215 | "idiom" : "watch", 216 | "role" : "notificationCenter", 217 | "scale" : "2x", 218 | "size" : "24x24", 219 | "subtype" : "38mm" 220 | }, 221 | { 222 | "filename" : "55.png", 223 | "idiom" : "watch", 224 | "role" : "notificationCenter", 225 | "scale" : "2x", 226 | "size" : "27.5x27.5", 227 | "subtype" : "42mm" 228 | }, 229 | { 230 | "filename" : "58.png", 231 | "idiom" : "watch", 232 | "role" : "companionSettings", 233 | "scale" : "2x", 234 | "size" : "29x29" 235 | }, 236 | { 237 | "filename" : "87.png", 238 | "idiom" : "watch", 239 | "role" : "companionSettings", 240 | "scale" : "3x", 241 | "size" : "29x29" 242 | }, 243 | { 244 | "idiom" : "watch", 245 | "role" : "notificationCenter", 246 | "scale" : "2x", 247 | "size" : "33x33", 248 | "subtype" : "45mm" 249 | }, 250 | { 251 | "filename" : "80.png", 252 | "idiom" : "watch", 253 | "role" : "appLauncher", 254 | "scale" : "2x", 255 | "size" : "40x40", 256 | "subtype" : "38mm" 257 | }, 258 | { 259 | "filename" : "88.png", 260 | "idiom" : "watch", 261 | "role" : "appLauncher", 262 | "scale" : "2x", 263 | "size" : "44x44", 264 | "subtype" : "40mm" 265 | }, 266 | { 267 | "idiom" : "watch", 268 | "role" : "appLauncher", 269 | "scale" : "2x", 270 | "size" : "46x46", 271 | "subtype" : "41mm" 272 | }, 273 | { 274 | "filename" : "100.png", 275 | "idiom" : "watch", 276 | "role" : "appLauncher", 277 | "scale" : "2x", 278 | "size" : "50x50", 279 | "subtype" : "44mm" 280 | }, 281 | { 282 | "idiom" : "watch", 283 | "role" : "appLauncher", 284 | "scale" : "2x", 285 | "size" : "51x51", 286 | "subtype" : "45mm" 287 | }, 288 | { 289 | "idiom" : "watch", 290 | "role" : "appLauncher", 291 | "scale" : "2x", 292 | "size" : "54x54", 293 | "subtype" : "49mm" 294 | }, 295 | { 296 | "filename" : "172.png", 297 | "idiom" : "watch", 298 | "role" : "quickLook", 299 | "scale" : "2x", 300 | "size" : "86x86", 301 | "subtype" : "38mm" 302 | }, 303 | { 304 | "filename" : "196.png", 305 | "idiom" : "watch", 306 | "role" : "quickLook", 307 | "scale" : "2x", 308 | "size" : "98x98", 309 | "subtype" : "42mm" 310 | }, 311 | { 312 | "filename" : "216.png", 313 | "idiom" : "watch", 314 | "role" : "quickLook", 315 | "scale" : "2x", 316 | "size" : "108x108", 317 | "subtype" : "44mm" 318 | }, 319 | { 320 | "idiom" : "watch", 321 | "role" : "quickLook", 322 | "scale" : "2x", 323 | "size" : "117x117", 324 | "subtype" : "45mm" 325 | }, 326 | { 327 | "idiom" : "watch", 328 | "role" : "quickLook", 329 | "scale" : "2x", 330 | "size" : "129x129", 331 | "subtype" : "49mm" 332 | }, 333 | { 334 | "filename" : "1024.png", 335 | "idiom" : "watch-marketing", 336 | "scale" : "1x", 337 | "size" : "1024x1024" 338 | } 339 | ], 340 | "info" : { 341 | "author" : "xcode", 342 | "version" : 1 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Colors/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Colors/background.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.969", 9 | "green" : "0.949", 10 | "red" : "0.949" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.063", 27 | "green" : "0.063", 28 | "red" : "0.063" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Colors/button.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.000", 9 | "green" : "0.000", 10 | "red" : "0.000" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "1.000", 27 | "green" : "1.000", 28 | "red" : "1.000" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Colors/cardBackground.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "1.000", 9 | "green" : "1.000", 10 | "red" : "1.000" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "display-p3", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.114", 27 | "green" : "0.110", 28 | "red" : "0.110" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Colors/grabber.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.570", 9 | "green" : "0.570", 10 | "red" : "0.570" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.921", 27 | "green" : "0.921", 28 | "red" : "0.921" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Colors/lightShadow.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "0.146", 8 | "blue" : "0x00", 9 | "green" : "0x00", 10 | "red" : "0x00" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "0.222", 26 | "blue" : "0xFF", 27 | "green" : "0xFF", 28 | "red" : "0xFF" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Colors/shadow.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.837", 9 | "green" : "0.837", 10 | "red" : "0.837" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.063", 27 | "green" : "0.063", 28 | "red" : "0.063" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Colors/sheet.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "1.000", 9 | "green" : "1.000", 10 | "red" : "1.000" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.130", 27 | "green" : "0.130", 28 | "red" : "0.130" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Colors/text.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "1.000", 9 | "green" : "1.000", 10 | "red" : "1.000" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.000", 27 | "green" : "0.000", 28 | "red" : "0.000" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/bac.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "bac.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/bac.imageset/bac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/bac.imageset/bac.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/defaultQRImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "defaultQRImage.jpeg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/defaultQRImage.imageset/defaultQRImage.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/defaultQRImage.imageset/defaultQRImage.jpeg -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/ww.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Group 1248.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/ww.imageset/Group 1248.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UlianaGritchina/QRCodeSwiftUI/188634d644cf9ff20d9221e4db2f643f636691c8/QRCodeSwiftUI/SupportingFiles/Assets.xcassets/Images/ww.imageset/Group 1248.png -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Extensions/Color + Extension.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | extension Color { 4 | static let sheetColor = Color("sheet") 5 | static let shadowColor = Color("shadow") 6 | static let textColor = Color("text") 7 | static let buttonColor = Color("button") 8 | static let grabberColor = Color("grabber") 9 | static let lightShadowColor = Color("lightShadow") 10 | } 11 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Extensions/UIApplication+Extension.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | extension UIApplication { 4 | func endEditing() { 5 | sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /QRCodeSwiftUI/SupportingFiles/QRCodeSwiftUIApp.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | @main 4 | struct QRCodeSwiftUIApp: App { 5 | @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate 6 | @StateObject var listViewModel: SavedCodesViewViewModel = SavedCodesViewViewModel() 7 | var body: some Scene { 8 | WindowGroup { 9 | TabViewView() 10 | .environmentObject(listViewModel) 11 | } 12 | } 13 | } 14 | class AppDelegate: NSObject, UIApplicationDelegate { 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 17 | configureTabBar() 18 | return true 19 | } 20 | 21 | private func configureTabBar() { 22 | let tabBarAppearance = UITabBarAppearance() 23 | tabBarAppearance.configureWithDefaultBackground() 24 | UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QR-Code Generator 2 | 3 | iOS App for generating custom QR-codes. SwiftUI MVVM 4 | 5 | ![Group 24](https://github.com/UlianaGritchina/QRCodeSwiftUI/assets/95241900/abeb882f-b1f9-463d-bc92-b6e58ad1e82b) 6 | 7 | QR generate method: 8 | ``` 9 | func generateQRCode(background: Color = .white, foregroundColor: Color = .black, content: String) -> Data? { 10 | var qrCodeImageData: Data? 11 | let backgroundColor = UIColor(background) 12 | let foregroundColor = UIColor(foregroundColor) 13 | let data = content.data(using: String.Encoding.utf8) 14 | if let filter = CIFilter(name: "CIQRCodeGenerator") { 15 | guard let colorFilter = CIFilter(name: "CIFalseColor") else { return nil } 16 | filter.setValue(data, forKey: "inputMessage") 17 | filter.setValue("H", forKey: "inputCorrectionLevel") 18 | colorFilter.setValue(filter.outputImage, forKey: "inputImage") 19 | colorFilter.setValue(CIColor(color: backgroundColor), forKey: "inputColor1") // Background 20 | colorFilter.setValue(CIColor(color: foregroundColor), forKey: "inputColor0") // Foreground 21 | guard let outputImage = colorFilter.outputImage else { return nil } 22 | let transform = CGAffineTransform(scaleX: 20, y: 20) 23 | let scaledCIImage = outputImage.transformed(by: transform) 24 | 25 | qrCodeImageData = UIImage(ciImage: scaledCIImage).pngData() 26 | } 27 | return qrCodeImageData 28 | } 29 | 30 | ``` 31 | --------------------------------------------------------------------------------