Skip to content

Commit 2b9c4f0

Browse files
committed
Support dragging timezones out of the app w/ json and string reps
1 parent 25ef076 commit 2b9c4f0

3 files changed

Lines changed: 95 additions & 2 deletions

File tree

Elsewhen.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
637839B226EBF5FD0055A10D /* ConvertTimeIntentHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637839B126EBF5FD0055A10D /* ConvertTimeIntentHandling.swift */; };
3434
637839B526EBF8130055A10D /* FormatCodeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637839B426EBF8130055A10D /* FormatCodeExtension.swift */; };
3535
637839B626EBF9690055A10D /* DateHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6378398426EB80F50055A10D /* DateHelpers.swift */; };
36+
637839CB26ED11360055A10D /* TimeZone+ItemProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637839CA26ED11360055A10D /* TimeZone+ItemProvider.swift */; };
3637
/* End PBXBuildFile section */
3738

3839
/* Begin PBXContainerItemProxy section */
@@ -96,6 +97,7 @@
9697
637839AF26EBF4910055A10D /* Intents.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = Intents.intentdefinition; sourceTree = "<group>"; };
9798
637839B126EBF5FD0055A10D /* ConvertTimeIntentHandling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConvertTimeIntentHandling.swift; sourceTree = "<group>"; };
9899
637839B426EBF8130055A10D /* FormatCodeExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormatCodeExtension.swift; sourceTree = "<group>"; };
100+
637839CA26ED11360055A10D /* TimeZone+ItemProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TimeZone+ItemProvider.swift"; sourceTree = "<group>"; };
99101
/* End PBXFileReference section */
100102

101103
/* Begin PBXFrameworksBuildPhase section */
@@ -193,6 +195,7 @@
193195
isa = PBXGroup;
194196
children = (
195197
6378397D26EA5FD60055A10D /* UIApplication+clearLaunchScreenCache.swift */,
198+
637839CA26ED11360055A10D /* TimeZone+ItemProvider.swift */,
196199
);
197200
path = Extensions;
198201
sourceTree = "<group>";
@@ -386,6 +389,7 @@
386389
5EAB48DD26E624CD00B04A60 /* TimezoneChoiceView.swift in Sources */,
387390
5EE70E2726ECCC0700F3F164 /* TimeCodeGeneratorView.swift in Sources */,
388391
6378398726EBA7C60055A10D /* DateTimeSelection.swift in Sources */,
392+
637839CB26ED11360055A10D /* TimeZone+ItemProvider.swift in Sources */,
389393
6378398326EB80C30055A10D /* ResultSheet.swift in Sources */,
390394
6378398526EB80F50055A10D /* DateHelpers.swift in Sources */,
391395
635C8FA726E66E8300361B08 /* DiscordFormattedDate.swift in Sources */,
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//
2+
// TimeZone+ItemProvider.swift
3+
// TimeZone+ItemProvider
4+
//
5+
// Created by David on 11/09/2021.
6+
//
7+
8+
import Foundation
9+
import UniformTypeIdentifiers
10+
11+
let jsonEncoder = JSONEncoder()
12+
13+
extension TimeZone {
14+
class ItemProvider: NSObject, NSItemProviderWriting, Codable {
15+
let identifier: String
16+
let name: String?
17+
let abbreviation: String?
18+
let flag: String
19+
20+
var resolvedName: String {
21+
"\(self.flag) \(self.name ?? self.identifier)"
22+
}
23+
24+
init(from timezone: TimeZone) {
25+
self.identifier = timezone.identifier
26+
self.name = timezone.localizedName(for: .standard, locale: .current)
27+
self.abbreviation = timezone.abbreviation()
28+
self.flag = flagForTimeZone(timezone)
29+
}
30+
31+
static var writableTypeIdentifiersForItemProvider: [String] = [
32+
UTType.json.identifier,
33+
UTType.text.identifier, UTType.utf8PlainText.identifier, UTType.plainText.identifier
34+
]
35+
36+
func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? {
37+
switch typeIdentifier {
38+
case UTType.json.identifier:
39+
return self.loadJson(forItemProviderCompletionHandler: completionHandler)
40+
case UTType.text.identifier,
41+
UTType.utf8PlainText.identifier,
42+
UTType.plainText.identifier:
43+
return self.loadUtf8String(forItemProviderCompletionHandler: completionHandler)
44+
default:
45+
completionHandler(nil, ItemProviderError.unrecognisedType(identifier: typeIdentifier))
46+
return nil
47+
}
48+
}
49+
50+
func loadJson(forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? {
51+
do {
52+
completionHandler(try jsonEncoder.encode(self), nil)
53+
} catch {
54+
completionHandler(nil, error)
55+
}
56+
return nil
57+
}
58+
59+
func loadUtf8String(forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? {
60+
completionHandler(Data(self.resolvedName.utf8), nil)
61+
return nil
62+
}
63+
}
64+
65+
var itemProvider: ItemProvider {
66+
TimeZone.ItemProvider(from: self)
67+
}
68+
}
69+
70+
enum ItemProviderError: LocalizedError {
71+
case unrecognisedType(identifier: String)
72+
73+
var errorDescription: String? {
74+
return String.localizedStringWithFormat(NSLocalizedString("ItemProvidingFailed: %@", tableName: "Errors", comment: ""), failureReason!)
75+
}
76+
77+
var failureReason: String? {
78+
switch self {
79+
case .unrecognisedType(let identifier):
80+
return String.localizedStringWithFormat(NSLocalizedString("UnrecognisedUTI: %@", tableName: "Errors", comment: ""), identifier)
81+
}
82+
}
83+
84+
var recoverySuggestion: String? {
85+
"Please contact support"
86+
}
87+
}

Elsewhen/Views/MykeMode.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
//
77

88
import SwiftUI
9-
import UniformTypeIdentifiers
109

1110
struct MykeMode: View {
1211

@@ -45,7 +44,10 @@ struct MykeMode: View {
4544
}
4645
}
4746
.onDrag {
48-
NSItemProvider(item: tz.identifier.data(using: .utf8)! as NSData, typeIdentifier: UTType.utf8PlainText.identifier)
47+
let tzItemProvider = tz.itemProvider
48+
let itemProvider = NSItemProvider(object: tzItemProvider)
49+
itemProvider.suggestedName = tzItemProvider.resolvedName
50+
return itemProvider
4951
}
5052
}
5153
.onMove(perform: move)

0 commit comments

Comments
 (0)