Skip to content

Commit 39075c0

Browse files
committed
Initial commit
1 parent dd65627 commit 39075c0

File tree

75 files changed

+2966
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+2966
-2
lines changed

.DS_Store

8 KB
Binary file not shown.

Podfile

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Uncomment the next line to define a global platform for your project
2+
# platform :ios, '9.0'
3+
4+
target 'Qode' do
5+
# Comment the next line if you don't want to use dynamic frameworks
6+
use_frameworks!
7+
8+
# Pods for Qode
9+
pod 'Highlightr'
10+
pod 'IQKeyboardManagerSwift'
11+
12+
end

Podfile.lock

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
PODS:
2+
- Highlightr (2.1.0)
3+
- IQKeyboardManagerSwift (6.5.6)
4+
5+
DEPENDENCIES:
6+
- Highlightr
7+
- IQKeyboardManagerSwift
8+
9+
SPEC REPOS:
10+
trunk:
11+
- Highlightr
12+
- IQKeyboardManagerSwift
13+
14+
SPEC CHECKSUMS:
15+
Highlightr: 595f3e100737c8de41113385da8bd0b5b65212c6
16+
IQKeyboardManagerSwift: c7df9d2deb356c04522f5c4b7b6e4ce4d8ed94fe
17+
18+
PODFILE CHECKSUM: eeacfa45647d199ccd7e0fc2690f5b94ae53a008
19+
20+
COCOAPODS: 1.10.0

Qode.xcodeproj/project.pbxproj

+693
Large diffs are not rendered by default.

Qode.xcodeproj/project.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>

Qode.xcworkspace/contents.xcworkspacedata

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>

Qode/.DS_Store

6 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// String+CapitalizeFirstLetter.swift
3+
// Qode
4+
//
5+
// Created by Jakub "GPH4PPY" Dąbrowski on 29/04/2021.
6+
//
7+
8+
import Foundation
9+
10+
// These methods set the uppercase letter for the first letter of the String.
11+
extension String {
12+
func capitalizingFirstLetter() -> String {
13+
return prefix(1).capitalized + dropFirst()
14+
}
15+
16+
mutating func capitalizeFirstLetter() {
17+
self = self.capitalizingFirstLetter()
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// String+CheckIfContainsEmoji.swift
3+
// Qode
4+
//
5+
// Created by Jakub "GPH4PPY" Dąbrowski on 13/05/2021.
6+
//
7+
8+
import Foundation
9+
10+
extension String {
11+
var containsEmoji: Bool { contains { $0.isEmoji } }
12+
}
13+
14+
extension Character {
15+
/// A simple emoji is one scalar and presented to the user as an Emoji
16+
var isSimpleEmoji: Bool {
17+
guard let firstScalar = unicodeScalars.first else { return false }
18+
return firstScalar.properties.isEmoji && firstScalar.value > 0x238C
19+
}
20+
21+
/// Checks if the scalars will be merged into an emoji
22+
var isCombinedIntoEmoji: Bool { unicodeScalars.count > 1 && unicodeScalars.first?.properties.isEmoji ?? false }
23+
24+
var isEmoji: Bool { isSimpleEmoji || isCombinedIntoEmoji }
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// UserDefaults+GetAndSetUIColors.swift
3+
// Qode
4+
//
5+
// Created by Jakub "GPH4PPY" Dąbrowski on 29/04/2021.
6+
//
7+
8+
import UIKit
9+
10+
extension UserDefaults {
11+
/// This method gets the UIColor from the given key (String).
12+
/// - Parameter key: The key with which the value will be associated.
13+
/// - Returns: Optional UIColor
14+
func colorForKey(key: String) -> UIColor? {
15+
var colorReturnded: UIColor?
16+
17+
if let colorData = data(forKey: key) {
18+
do {
19+
if let color = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(colorData) as? UIColor {
20+
colorReturnded = color
21+
}
22+
} catch {
23+
print(error.localizedDescription)
24+
}
25+
}
26+
27+
return colorReturnded
28+
}
29+
30+
/// This method sets the UIColor from the given key (String).
31+
/// - Parameters:
32+
/// - color: The color to be assigned to the given key.
33+
/// - key: The key with which the value will be associated.
34+
func setColor(color: UIColor?, forKey key: String) {
35+
var colorData: NSData?
36+
37+
if let color = color {
38+
do {
39+
let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: false) as NSData?
40+
colorData = data
41+
} catch {
42+
print(error.localizedDescription)
43+
}
44+
}
45+
46+
set(colorData, forKey: key)
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// GeneratorViewController+LanguageOptions.swift
3+
// Qode
4+
//
5+
// Created by Jakub "GPH4PPY" Dąbrowski on 01/05/2021.
6+
//
7+
8+
import UIKit
9+
10+
// MARK: - Language Options
11+
extension GeneratorViewController {
12+
/// This method setups the language, thanks to which the code syntax is highlighted.
13+
/// - Returns: NSAttributedString which will be assigned to TextView
14+
@discardableResult internal func setupLanguage() -> NSAttributedString? {
15+
textStorage.language = selectedLanguage.capitalizingFirstLetter()
16+
return highlightr?.highlight(textStorage.string, as: selectedLanguage)
17+
}
18+
19+
/// This method changes the currently selected language so the code syntax can be highlighted.
20+
@objc internal func changeLanguage() {
21+
let device = UIDevice.current.userInterfaceIdiom
22+
23+
DispatchQueue.main.async {
24+
// Create sheet
25+
let ac = UIAlertController(title: LocalizedStrings.language,
26+
message: LocalizedStrings.selectLanguageBody,
27+
preferredStyle: device == .pad ? .alert : .actionSheet)
28+
29+
// Add all languages actions
30+
self.highlightr?.supportedLanguages().forEach({ language in
31+
ac.addAction(UIAlertAction(title: language.capitalizingFirstLetter(), style: .default, handler: { _ in
32+
self.selectedLanguage = language
33+
self.setupLanguage()
34+
}))
35+
})
36+
37+
// Add cancel action
38+
ac.addAction(UIAlertAction(title: LocalizedStrings.cancel, style: .destructive))
39+
40+
// Present alert controller
41+
self.present(ac, animated: true)
42+
}
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//
2+
// GeneratorViewController+PresentableViews.swift
3+
// Qode
4+
//
5+
// Created by Jakub "GPH4PPY" Dąbrowski on 01/05/2021.
6+
//
7+
8+
import UIKit
9+
10+
// MARK: - Presentable Views
11+
extension GeneratorViewController {
12+
/// This method setups the ViewController components.
13+
internal func setupView() {
14+
// Set theme
15+
textStorage.highlightr.setTheme(to: selectedTheme)
16+
17+
// Create layout manager
18+
let layoutManager = NSLayoutManager()
19+
textStorage.addLayoutManager(layoutManager)
20+
21+
// Create text container
22+
let textContainer = NSTextContainer(size: CGSize(width: paddingView.bounds.width, height: paddingView.bounds.height - 10))
23+
layoutManager.addTextContainer(textContainer)
24+
25+
// Create TextView
26+
let textView = UITextView(frame: paddingView.bounds, textContainer: textContainer)
27+
textView.delegate = self
28+
textView.attributedText = setupLanguage()
29+
textView.autocorrectionType = .no
30+
textView.autocapitalizationType = .none
31+
textView.returnKeyType = .done
32+
33+
// Add TextView to the padding view
34+
paddingView.addSubview(textView)
35+
36+
// Setup TextView constraints
37+
textView.translatesAutoresizingMaskIntoConstraints = false
38+
39+
NSLayoutConstraint.activate([
40+
textView.topAnchor.constraint(equalTo: paddingView.topAnchor),
41+
textView.bottomAnchor.constraint(equalTo: paddingView.bottomAnchor),
42+
43+
textView.widthAnchor.constraint(equalTo: paddingView.widthAnchor),
44+
textView.heightAnchor.constraint(equalTo: paddingView.heightAnchor)
45+
])
46+
}
47+
48+
/// This method shows the ViewController which has a QR code generated.
49+
@objc internal func generateQRCode() {
50+
let code = textStorage.string
51+
var alert: UIAlertController!
52+
53+
DispatchQueue.main.async { [self] in
54+
if code.count >= 2200 {
55+
// Check that the code is not too long.
56+
// In theory, the QR code can hold up to about 4000 characters, but above 2200 it doesn't work, because the input data is too big.
57+
alert = createAlert(title: LocalizedStrings.notTooMuch,
58+
message: LocalizedStrings.tooLongCode,
59+
action: LocalizedStrings.ok)
60+
present(alert, animated: true)
61+
} else if code.count == 0 {
62+
// Check if the code is not empty.
63+
alert = createAlert(title: LocalizedStrings.emptyCode,
64+
message: LocalizedStrings.emptyCodeBody,
65+
action: LocalizedStrings.ok)
66+
present(alert, animated: true)
67+
} else if checkForIllegalCharacters(string: code) || code.containsEmoji {
68+
// Check if the code does not contain illegal characters.
69+
alert = createAlert(title: LocalizedStrings.illegalCharacters,
70+
message: LocalizedStrings.illegalCharactersAlert,
71+
action: LocalizedStrings.ok)
72+
present(alert, animated: true)
73+
} else {
74+
// Show ViewController with generated QR code.
75+
if let vc = storyboard?.instantiateViewController(identifier: "generatedCodeVC") as? QRCodeOutputViewController {
76+
vc.code = code
77+
navigationController?.pushViewController(vc, animated: true)
78+
}
79+
}
80+
}
81+
}
82+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// GeneratorViewController+Validation.swift
3+
// Qode
4+
//
5+
// Created by Jakub "GPH4PPY" Dąbrowski on 01/05/2021.
6+
//
7+
8+
import Foundation
9+
10+
// MARK: - Validation
11+
extension GeneratorViewController {
12+
/// This method checks if the code contains illegal characters.
13+
/// - Parameter string: Code which will be checked
14+
/// - Returns: Bool value if string contains illegal character
15+
internal func checkForIllegalCharacters(string: String) -> Bool {
16+
if string.rangeOfCharacter(from: AppData.illegalCharacters) != nil {
17+
// Found illegal characters
18+
return true
19+
} else {
20+
// Didn't find illegal characters
21+
return false
22+
}
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// QRCodeOutputViewController+QRCodeManagement.swift
3+
// Qode
4+
//
5+
// Created by Jakub "GPH4PPY" Dąbrowski on 02/05/2021.
6+
//
7+
8+
import UIKit
9+
import CoreImage.CIFilterBuiltins
10+
11+
// MARK: - QR Code Management
12+
extension QRCodeOutputViewController {
13+
/// This opens up the UIActivityViewController which allows sharing the QR code.
14+
@objc internal func shareCode() {
15+
let child = SpinnerViewController()
16+
17+
// Add the Spinner View Controller
18+
addChild(child)
19+
child.view.frame = view.frame
20+
view.addSubview(child.view)
21+
child.didMove(toParent: self)
22+
23+
// Initialize UIActivityViewController
24+
DispatchQueue.global(qos: .userInteractive).async {
25+
if let code = self.code {
26+
if let image = self.generateQRCode(from: code) {
27+
let items = [image]
28+
let ac = UIActivityViewController(activityItems: items, applicationActivities: [])
29+
30+
// Stop ActivityIndicator and show UIActivityViewController
31+
DispatchQueue.main.async {
32+
ac.popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
33+
self.present(ac, animated: true)
34+
35+
child.willMove(toParent: nil)
36+
child.view.removeFromSuperview()
37+
child.removeFromParent()
38+
}
39+
}
40+
}
41+
}
42+
}
43+
44+
/// This method generates a QR code that can then be scanned or shared.
45+
/// - Parameter string: Code from which the QR code will be generated
46+
/// - Returns: Optional UIImage (QR code)
47+
func generateQRCode(from string: String) -> UIImage? {
48+
let data = Data(string.utf8)
49+
let filter = CIFilter.qrCodeGenerator()
50+
let context = CIContext()
51+
let transform = CGAffineTransform(scaleX: 10, y: 10)
52+
53+
filter.setValue(data, forKey: "inputMessage")
54+
55+
if let qrCodeImage = filter.outputImage?.transformed(by: transform) {
56+
if let qrCodeCGImage = context.createCGImage(qrCodeImage, from: qrCodeImage.extent) {
57+
return UIImage(cgImage: qrCodeCGImage)
58+
}
59+
}
60+
61+
return nil
62+
}
63+
}

0 commit comments

Comments
 (0)