Skip to content

Commit 895550b

Browse files
committed
chore: add swift lint
1 parent 5ae61a0 commit 895550b

13 files changed

+125
-99
lines changed

Diff for: example/.prettierignore

-7
This file was deleted.

Diff for: example/metro.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const config = {
2222
// So we block them at the root, and alias them to the versions in example's node_modules
2323
resolver: {
2424
blacklistRE: exclusionList(
25-
modules.map((m) => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)),
25+
modules.map((m) => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`))
2626
),
2727

2828
extraNodeModules: modules.reduce((acc, name) => {

Diff for: example/package.json

+2-15
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88
"setup": "npx expo prebuild",
99
"clean": "yarn setup --clean",
1010
"doctor": "npx expo-doctor",
11-
"ios": "expo run:ios",
12-
"web": "expo start --web",
13-
"typecheck": "tsc --noEmit -p . --pretty",
14-
"tidy": "prettier --write \"**/*.{js,json,ts,tsx}\""
11+
"ios": "expo run:ios"
1512
},
1613
"dependencies": {
1714
"expo": "~50.0.13",
@@ -28,17 +25,7 @@
2825
"@babel/preset-env": "^7.20.0",
2926
"@babel/runtime": "^7.20.0",
3027
"@react-native/metro-config": "^0.73.5",
31-
"@react-native/typescript-config": "^0.74.0",
32-
"@types/react": "~18.2.45",
33-
"babel-plugin-module-resolver": "^5.0.0",
34-
"prettier": "^3.2.5",
35-
"typescript": "^5.1.3"
36-
},
37-
"prettier": {
38-
"printWidth": 100,
39-
"semi": false,
40-
"singleQuote": true,
41-
"trailingComma": "all"
28+
"babel-plugin-module-resolver": "^5.0.0"
4229
},
4330
"engines": {
4431
"node": ">=18"

Diff for: example/src/utils/mockPosition.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { Position } from './types'
55
*/
66
export const mockPosition = (
77
center: Position = [-105.358887, 39.113014],
8-
radiusKm = 10,
8+
radiusKm = 10
99
): Position => {
1010
const centerLng = center[0]
1111
const centerLat = center[1]

Diff for: ios/.swift-version

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5.2

Diff for: ios/.swiftformat

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--allman false
2+
--indent 2
3+
--exclude Pods,Generated
4+
5+
--disable andOperator
6+
--disable redundantReturn
7+
--disable wrapMultilineStatementBraces
8+
--disable organizeDeclarations
9+
10+
--enable markTypes
11+
12+
--enable isEmpty

Diff for: ios/.swiftlint.yml

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
disabled_rules:
2+
- identifier_name
3+
- trailing_comma
4+
- todo
5+
- type_body_length
6+
- cyclomatic_complexity
7+
- function_body_length
8+
- for_where
9+
opt_in_rules:
10+
- contains_over_filter_count
11+
- contains_over_filter_is_empty
12+
- contains_over_first_not_nil
13+
- contains_over_range_nil_comparison
14+
- empty_collection_literal
15+
- empty_count
16+
- empty_string
17+
- first_where
18+
- flatmap_over_map_reduce
19+
- last_where
20+
- reduce_boolean
21+
- reduce_into
22+
- yoda_condition
23+
- vertical_whitespace_opening_braces
24+
- vertical_whitespace_closing_braces
25+
- vertical_parameter_alignment_on_call
26+
- untyped_error_in_catch
27+
- unowned_variable_capture
28+
- unavailable_function
29+
- switch_case_on_newline
30+
- static_operator
31+
- strict_fileprivate
32+
- sorted_imports
33+
- sorted_first_last
34+
- required_enum_case
35+
- redundant_type_annotation
36+
- redundant_nil_coalescing
37+
- attributes
38+
- convenience_type
39+
analyzer_rules:
40+
- explicit_self
41+
- unused_declaration
42+
- unused_import
43+
44+
excluded: # paths to ignore during linting. Takes precedence over `included`.
45+
- Pods
46+
47+
# Adjust rule numbers
48+
line_length: 160
49+
file_length: 500
50+
51+
# reporter type (xcode, json, csv, checkstyle, codeclimate, junit, html, emoji, sonarqube, markdown, github-actions-logging)
52+
reporter: "xcode"

Diff for: ios/Exify.swift

+20-23
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,18 @@ import PhotosUI
1111

1212
@objc(Exify)
1313
class Exify: NSObject {
14-
15-
func readExif(uri: String, resolve: @escaping RCTPromiseResolveBlock) -> Void {
14+
func readExif(uri: String, resolve: @escaping RCTPromiseResolveBlock) {
1615
guard let url = URL(string: uri) else {
1716
resolve(nil)
1817
return
1918
}
20-
19+
2120
readExifTags(from: url) { tags in
2221
resolve(tags)
2322
}
2423
}
2524

26-
func readExif(assetId: String, resolve: @escaping RCTPromiseResolveBlock) -> Void {
25+
func readExif(assetId: String, resolve: @escaping RCTPromiseResolveBlock) {
2726
guard let asset = getAssetBy(id: assetId) else {
2827
resolve(nil)
2928
return
@@ -32,62 +31,61 @@ class Exify: NSObject {
3231
let imageOptions = PHContentEditingInputRequestOptions()
3332
imageOptions.isNetworkAccessAllowed = true
3433

35-
asset.requestContentEditingInput(with: imageOptions) { contentInput, info in
34+
asset.requestContentEditingInput(with: imageOptions) { contentInput, _ in
3635
guard let url = contentInput?.fullSizeImageURL else {
3736
resolve(nil)
3837
return
3938
}
40-
39+
4140
readExifTags(from: url) { tags in
4241
resolve(tags)
4342
}
4443
}
4544
}
46-
47-
func writeExif(assetId: String, tags: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
45+
46+
func writeExif(assetId: String, tags: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
4847
guard let asset = getAssetBy(id: assetId) else {
4948
reject("Error", "Cannot retrieve asset.", nil)
5049
return
5150
}
52-
51+
5352
let imageOptions = PHContentEditingInputRequestOptions()
5453
imageOptions.isNetworkAccessAllowed = true
55-
54+
5655
asset.requestContentEditingInput(with: imageOptions) { contentInput, _ in
5756
guard let contentInput, let url = contentInput.fullSizeImageURL else {
5857
reject("Error", "Unable to read metadata from asset", nil)
5958
return
6059
}
61-
60+
6261
updateMetadata(url: url, with: tags) { metadata, data in
6362
guard let metadata, let data else {
6463
reject("Error", "Could not update metadata", nil)
6564
return
6665
}
67-
66+
6867
do {
69-
try PHPhotoLibrary.shared().performChangesAndWait{
68+
try PHPhotoLibrary.shared().performChangesAndWait {
7069
let request = PHAssetCreationRequest.forAsset()
7170
request.addResource(with: .photo, data: data, options: nil)
7271
request.creationDate = Date()
73-
72+
7473
let newAssetId = request.placeholderForCreatedAsset!.localIdentifier
7574
resolve([
7675
"uri": "ph://\(newAssetId)",
7776
"assetId": newAssetId,
7877
"tags": getExifTags(from: metadata),
7978
])
80-
8179
}
82-
} catch let error {
80+
} catch {
8381
reject("Error", "Could not save to image file", nil)
8482
print(error)
8583
}
8684
}
8785
}
8886
}
89-
90-
func writeExif(uri: String, tags: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
87+
88+
func writeExif(uri: String, tags: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
9189
guard let url = URL(string: uri) else {
9290
reject("Error", "Invalid URL", nil)
9391
return
@@ -98,7 +96,7 @@ class Exify: NSObject {
9896
reject("Error", "Could not update metadata", nil)
9997
return
10098
}
101-
99+
102100
do {
103101
// Write to the current file
104102
try data.write(to: url, options: .atomic)
@@ -107,16 +105,15 @@ class Exify: NSObject {
107105
"uri": uri,
108106
"tags": getExifTags(from: metadata),
109107
])
110-
111-
} catch let error {
108+
} catch {
112109
reject("Error", "Could not save to image file", nil)
113110
print(error)
114111
}
115112
}
116113
}
117114

118115
@objc(readAsync:withResolver:withRejecter:)
119-
func readAsync(uri: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
116+
func readAsync(uri: String, resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock) {
120117
if uri.starts(with: "ph://") {
121118
let assetId = String(uri[uri.index(uri.startIndex, offsetBy: 5)...])
122119
readExif(assetId: assetId, resolve: resolve)
@@ -126,7 +123,7 @@ class Exify: NSObject {
126123
}
127124

128125
@objc(writeAsync:withExif:withResolver:withRejecter:)
129-
func writeAsync(uri: String, tags: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
126+
func writeAsync(uri: String, tags: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
130127
if uri.starts(with: "ph://") {
131128
let assetId = String(uri[uri.index(uri.startIndex, offsetBy: 5)...])
132129
writeExif(assetId: assetId, tags: tags, resolve: resolve, reject: reject)

Diff for: ios/ExifyUtils.swift

+19-20
Original file line numberDiff line numberDiff line change
@@ -27,64 +27,64 @@ func getAssetsBy(assetIds: [String]) -> PHFetchResult<PHAsset> {
2727
return PHAsset.fetchAssets(withLocalIdentifiers: assetIds, options: options)
2828
}
2929

30-
func addTagEntries(from dictionary: CFString, metadata: NSDictionary, to tags: NSMutableDictionary) -> Void {
30+
func addTagEntries(from dictionary: CFString, metadata: NSDictionary, to tags: NSMutableDictionary) {
3131
if let entries = metadata[dictionary] as? [String: Any] {
3232
tags.addEntries(from: entries)
3333
}
3434
}
3535

3636
func getExifTags(from metadata: NSDictionary) -> [String: Any] {
3737
let tags: NSMutableDictionary = [:]
38-
38+
3939
// Add root non-dictionary properties
4040
for (key, value) in metadata {
4141
if value as? [String: Any] == nil {
4242
tags[key] = value
4343
}
4444
}
45-
45+
4646
// Append all {Exif} properties
4747
addTagEntries(from: kCGImagePropertyExifDictionary, metadata: metadata, to: tags)
48-
48+
4949
// Prefix {GPS} dictionary with "GPS"
5050
if let gps = metadata[kCGImagePropertyGPSDictionary as String] as? [String: Any] {
5151
for (key, value) in gps {
5252
tags["GPS" + key] = value
5353
}
5454
}
55-
55+
5656
// Include tags from formats
5757
addTagEntries(from: kCGImagePropertyTIFFDictionary, metadata: metadata, to: tags)
5858
addTagEntries(from: kCGImagePropertyPNGDictionary, metadata: metadata, to: tags)
5959
addTagEntries(from: kCGImagePropertyHEICSDictionary, metadata: metadata, to: tags)
60-
61-
return tags as! [String: Any]
60+
61+
return tags as? [String: Any] ?? [:]
6262
}
6363

64-
func readExifTags(from url: URL?, completionHandler: ([String: Any]?) -> Void) -> Void {
64+
func readExifTags(from url: URL?, completionHandler: ([String: Any]?) -> Void) {
6565
guard let url, let sourceImage = CGImageSourceCreateWithURL(url as CFURL, nil),
6666
let metadataDict = CGImageSourceCopyPropertiesAtIndex(sourceImage, 0, nil) else {
6767
completionHandler(nil)
6868
return
6969
}
70-
70+
7171
let tags = getExifTags(from: metadataDict)
7272
completionHandler(tags)
7373
}
7474

75-
func updateMetadata(url: URL, with tags: [String: Any], completionHanlder: (NSDictionary?, Data?) -> Void) -> Void {
75+
func updateMetadata(url: URL, with tags: [String: Any], completionHanlder: (NSDictionary?, Data?) -> Void) {
7676
guard let cgImageSource = CGImageSourceCreateWithURL(url as CFURL, nil) else {
7777
completionHanlder(nil, nil)
7878
return
7979
}
80-
80+
8181
let metadataDict = CGImageSourceCopyPropertiesAtIndex(cgImageSource, 0, nil) ?? [:] as CFDictionary
8282
let metadata = NSMutableDictionary(dictionary: metadataDict)
8383

8484
// Append additional Exif data
8585
let exifDict = metadata[kCGImagePropertyExifDictionary as String] as? NSMutableDictionary
8686
exifDict?.addEntries(from: tags)
87-
87+
8888
// Handle GPS Tags
8989
var gpsDict = [String: Any]()
9090

@@ -102,15 +102,14 @@ func updateMetadata(url: URL, with tags: [String: Any], completionHanlder: (NSDi
102102
gpsDict[kCGImagePropertyGPSAltitude as String] = abs(altitude)
103103
gpsDict[kCGImagePropertyGPSAltitudeRef as String] = altitude >= 0 ? 0 : 1
104104
}
105-
105+
106106
if let gpsDate = tags["GPSDateStamp"] as? String {
107107
gpsDict[kCGImagePropertyGPSDateStamp as String] = gpsDate
108108
}
109-
109+
110110
if let gpsTime = tags["GPSTimeStamp"] as? String {
111111
gpsDict[kCGImagePropertyGPSTimeStamp as String] = gpsTime
112112
}
113-
114113

115114
if metadata[kCGImagePropertyGPSDictionary as String] == nil {
116115
metadata[kCGImagePropertyGPSDictionary as String] = gpsDict
@@ -119,20 +118,20 @@ func updateMetadata(url: URL, with tags: [String: Any], completionHanlder: (NSDi
119118
metadataGpsDict.addEntries(from: gpsDict)
120119
}
121120
}
122-
121+
123122
metadata.setObject(NSNumber(value: 1), forKey: kCGImageDestinationLossyCompressionQuality as NSString)
124-
123+
125124
let destinationData = NSMutableData()
126125

127126
guard let uiImage = UIImage(contentsOfFile: url.path),
128-
let sourceType = CGImageSourceGetType(cgImageSource),
129-
let destination = CGImageDestinationCreateWithData(destinationData, sourceType, 1, nil) else {
127+
let sourceType = CGImageSourceGetType(cgImageSource),
128+
let destination = CGImageDestinationCreateWithData(destinationData, sourceType, 1, nil) else {
130129
completionHanlder(nil, nil)
131130
return
132131
}
133132

134133
CGImageDestinationAddImage(destination, uiImage.cgImage!, metadata)
135134
CGImageDestinationFinalize(destination)
136-
135+
137136
completionHanlder(metadata, destinationData as Data)
138137
}

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"typecheck": "tsc --noEmit",
3232
"lint": "eslint --fix \"**/*.{js,ts,tsx}\"",
3333
"format": "prettier --write \"**/*.{js,ts,tsx}\"",
34-
"tidy": "yarn typecheck && yarn lint && yarn format",
34+
"tidy": "yarn typecheck && yarn lint && yarn format && scripts/swiftlint.sh && scripts/swiftformat.sh",
3535
"clean": "del-cli android/build lib && yarn workspace exify-example clean",
3636
"prepare": "bob build",
3737
"release": "release-it"

Diff for: scripts/swiftformat.sh

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
if which swiftformat >/dev/null; then
4+
cd ios && swiftformat --quiet .
5+
else
6+
echo "error: SwiftFormat not installed, install with 'brew install swiftformat' (or manually from https://github.com/nicklockwood/SwiftFormat)"
7+
exit 1
8+
fi

0 commit comments

Comments
 (0)