react-native-ios-widget 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/plugin/build/index.d.ts +2 -2
- package/plugin/build/index.js +5 -5
- package/plugin/build/lib/getWidgetExtensionEntitlements.d.ts +4 -4
- package/plugin/build/lib/getWidgetExtensionEntitlements.js +5 -5
- package/plugin/build/lib/getWidgetFiles.d.ts +1 -2
- package/plugin/build/lib/getWidgetFiles.js +9 -10
- package/plugin/build/types.d.ts +1 -1
- package/plugin/build/withConfig.d.ts +2 -2
- package/plugin/build/withPodfile.d.ts +2 -2
- package/plugin/build/withPodfile.js +14 -14
- package/plugin/build/withWidgetExtensionEntitlements.d.ts +2 -2
- package/plugin/build/withXcode.d.ts +2 -2
- package/plugin/src/index.ts +7 -7
- package/plugin/src/lib/getWidgetExtensionEntitlements.ts +6 -6
- package/plugin/src/lib/getWidgetFiles.ts +8 -8
- package/plugin/src/types.ts +1 -1
- package/plugin/src/withConfig.ts +2 -2
- package/plugin/src/withPodfile.ts +16 -16
- package/plugin/src/withWidgetExtensionEntitlements.ts +2 -2
- package/plugin/src/withXcode.ts +2 -2
- package/_widgets/EmojiRanger/AdventureActivityConfiguration.swift +0 -71
- package/_widgets/EmojiRanger/AllCharactersView.swift +0 -43
- package/_widgets/EmojiRanger/Assets.xcassets/AccentColor.colorset/Contents.json +0 -11
- package/_widgets/EmojiRanger/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -13
- package/_widgets/EmojiRanger/Assets.xcassets/Contents.json +0 -6
- package/_widgets/EmojiRanger/Assets.xcassets/WidgetBackground.colorset/Contents.json +0 -11
- package/_widgets/EmojiRanger/Attributes.swift +0 -21
- package/_widgets/EmojiRanger/EmojiRanger.swift +0 -248
- package/_widgets/EmojiRanger/EmojiRangersWidget.intentdefinition +0 -118
- package/_widgets/EmojiRanger/EmojiRangersWidget.swift +0 -189
- package/_widgets/EmojiRanger/EmojiRangersWidgetBundle.swift +0 -21
- package/_widgets/EmojiRanger/ImageURLProtocol.swift +0 -66
- package/_widgets/EmojiRanger/Info.plist +0 -11
- package/_widgets/EmojiRanger/LeaderboardWidget.swift +0 -93
- package/_widgets/EmojiRanger/Module.swift +0 -94
- package/_widgets/PizzaDelivery/Assets.xcassets/AccentColor.colorset/Contents.json +0 -11
- package/_widgets/PizzaDelivery/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -13
- package/_widgets/PizzaDelivery/Assets.xcassets/Contents.json +0 -6
- package/_widgets/PizzaDelivery/Assets.xcassets/WidgetBackground.colorset/Contents.json +0 -11
- package/_widgets/PizzaDelivery/Attributes.swift +0 -15
- package/_widgets/PizzaDelivery/Info.plist +0 -11
- package/_widgets/PizzaDelivery/LiveActivity.swift +0 -108
- package/_widgets/PizzaDelivery/Module.swift +0 -94
- package/_widgets/PizzaDelivery/WidgetBundle.swift +0 -13
- package/_widgets/PizzaDelivery/Widgets.swift +0 -59
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
See the LICENSE.txt file for this sample’s licensing information.
|
|
3
|
-
|
|
4
|
-
Abstract:
|
|
5
|
-
Details about a hero, including a name, health level, avatar, and other properties.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import AppIntents
|
|
9
|
-
import WidgetKit
|
|
10
|
-
|
|
11
|
-
struct EmojiRanger: Hashable, Codable, Identifiable {
|
|
12
|
-
|
|
13
|
-
static var typeDisplayRepresentation: TypeDisplayRepresentation = "EmojiRanger"
|
|
14
|
-
|
|
15
|
-
static let LeaderboardWidgetKind: String = "LeaderboardWidget"
|
|
16
|
-
static let EmojiRangerWidgetKind: String = "EmojiRangerWidget"
|
|
17
|
-
|
|
18
|
-
var displayRepresentation: DisplayRepresentation {
|
|
19
|
-
DisplayRepresentation(title: "\(avatar) \(name)")
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let name: String
|
|
23
|
-
let avatar: String
|
|
24
|
-
let healthLevel: Double
|
|
25
|
-
let heroType: String
|
|
26
|
-
let healthRecoveryRatePerHour: Double
|
|
27
|
-
let url: URL
|
|
28
|
-
let battleCode: URL
|
|
29
|
-
let level: Int
|
|
30
|
-
let exp: Int
|
|
31
|
-
let bio: String
|
|
32
|
-
|
|
33
|
-
var id: String {
|
|
34
|
-
name
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
static let panda = EmojiRanger(
|
|
38
|
-
name: "Power Panda",
|
|
39
|
-
avatar: "🐼",
|
|
40
|
-
healthLevel: 0.14,
|
|
41
|
-
heroType: "Forest Dweller",
|
|
42
|
-
healthRecoveryRatePerHour: 0.25,
|
|
43
|
-
url: URL(string: "game:///panda")!,
|
|
44
|
-
battleCode: URL(string: "game:///panda/battle")!,
|
|
45
|
-
level: 3,
|
|
46
|
-
exp: 600,
|
|
47
|
-
bio: "Power Panda loves eating bamboo shoots and leaves.")
|
|
48
|
-
|
|
49
|
-
static let egghead = EmojiRanger(
|
|
50
|
-
name: "Egghead",
|
|
51
|
-
avatar: "🦄",
|
|
52
|
-
healthLevel: 0.67,
|
|
53
|
-
heroType: "Free Ranger",
|
|
54
|
-
healthRecoveryRatePerHour: 0.22,
|
|
55
|
-
url: URL(string: "game:///egghead")!,
|
|
56
|
-
battleCode: URL(string: "game:///egghead/battle")!,
|
|
57
|
-
level: 5,
|
|
58
|
-
exp: 1000,
|
|
59
|
-
bio: "Egghead comes from the magical land of Eggopolis and flies through the air with their magnificent mane billowing.")
|
|
60
|
-
|
|
61
|
-
static let spouty = EmojiRanger(
|
|
62
|
-
name: "Spouty",
|
|
63
|
-
avatar: "🐳",
|
|
64
|
-
healthLevel: 0.99,
|
|
65
|
-
heroType: "Deep Sea Goer",
|
|
66
|
-
healthRecoveryRatePerHour: 0.59,
|
|
67
|
-
url: URL(string: "game:///spouty")!,
|
|
68
|
-
battleCode: URL(string: "game:///spouty/battle")!,
|
|
69
|
-
level: 50,
|
|
70
|
-
exp: 20_000,
|
|
71
|
-
bio: "Spouty rises from the depths to bring joy and laughter to everyone. They are best friends with Octo.")
|
|
72
|
-
|
|
73
|
-
static let availableHeros = [panda, egghead, spouty]
|
|
74
|
-
|
|
75
|
-
func hash(into hasher: inout Hasher) {
|
|
76
|
-
hasher.combine(name)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
var fullHealthDate: Date {
|
|
80
|
-
let healthNeeded = min(1 - healthLevel, 1)
|
|
81
|
-
let hoursUntilFullHealth = healthNeeded / healthRecoveryRatePerHour
|
|
82
|
-
let minutesUntilFullHealth = (hoursUntilFullHealth * 60)
|
|
83
|
-
let date = Calendar.current.date(byAdding: .minute, value: Int(minutesUntilFullHealth), to: Date())
|
|
84
|
-
|
|
85
|
-
return date ?? Date()
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
var injuryDate: Date {
|
|
89
|
-
let totalInjurySeconds = 3600 / healthRecoveryRatePerHour
|
|
90
|
-
let injuryDate = fullHealthDate.advanced(by: -totalInjurySeconds)
|
|
91
|
-
return injuryDate
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
static func heroFromName(name: String?) -> EmojiRanger {
|
|
95
|
-
guard let hero = (allHeros).first(where: { (hero) -> Bool in
|
|
96
|
-
return hero.name == name
|
|
97
|
-
}) else {
|
|
98
|
-
return .panda
|
|
99
|
-
}
|
|
100
|
-
return hero
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
static func heroFromURL(url: URL) -> EmojiRanger? {
|
|
104
|
-
guard let hero = (allHeros).first(where: { (hero) -> Bool in
|
|
105
|
-
return hero.url == url
|
|
106
|
-
}) else {
|
|
107
|
-
return .panda
|
|
108
|
-
}
|
|
109
|
-
return hero
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
static let session = ImageURLProtocol.urlSession()
|
|
113
|
-
|
|
114
|
-
static func loadLeaderboardData(completion:@escaping ([EmojiRanger]?, Error?) -> Void) {
|
|
115
|
-
// Save a faux API to the temporary directory and fetch it.
|
|
116
|
-
// In your app, you fetch it from a real API.
|
|
117
|
-
do {
|
|
118
|
-
let responseURL = FileManager.default.temporaryDirectory.appendingPathComponent("userData.json")
|
|
119
|
-
|
|
120
|
-
try fauxResponse.data(using: .utf8)?.write(to: responseURL)
|
|
121
|
-
session.dataTask(with: responseURL) { (data, response, error) in
|
|
122
|
-
if let playerData = data {
|
|
123
|
-
do {
|
|
124
|
-
let hero = try JSONDecoder().decode([EmojiRanger].self, from: playerData)
|
|
125
|
-
.sorted { $0.healthLevel > $1.healthLevel }
|
|
126
|
-
completion(hero, error)
|
|
127
|
-
} catch {
|
|
128
|
-
completion(nil, error)
|
|
129
|
-
}
|
|
130
|
-
} else {
|
|
131
|
-
completion(nil, error)
|
|
132
|
-
}
|
|
133
|
-
}.resume()
|
|
134
|
-
} catch {
|
|
135
|
-
completion(nil, error)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
static let appGroup = "<App Group Here>"
|
|
141
|
-
|
|
142
|
-
static func setLastSelectedHero(heroName: String) {
|
|
143
|
-
UserDefaults(suiteName: appGroup)?.setValue(heroName, forKey: "hero")
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
static func getLastSelectedHero() -> EmojiRanger? {
|
|
147
|
-
guard let name = UserDefaults(suiteName: appGroup)?.value(forKey: "hero") as? String else {
|
|
148
|
-
return nil
|
|
149
|
-
}
|
|
150
|
-
return EmojiRanger.heroFromName(name: name)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
static func superchargeHeros() {
|
|
154
|
-
var val = herosAreSupercharged()
|
|
155
|
-
val.toggle()
|
|
156
|
-
UserDefaults(suiteName: appGroup)?.setValue(val, forKey: "supercharged")
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
static func herosAreSupercharged() -> Bool {
|
|
160
|
-
guard let areCharged = UserDefaults(suiteName: appGroup)?.value(forKey: "supercharged") as? Bool else {
|
|
161
|
-
return false
|
|
162
|
-
}
|
|
163
|
-
return areCharged
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
let fauxResponse =
|
|
168
|
-
"""
|
|
169
|
-
[
|
|
170
|
-
{
|
|
171
|
-
"name": "Power Panda",
|
|
172
|
-
"avatar": "🐼",
|
|
173
|
-
"healthLevel": 0.99,
|
|
174
|
-
"heroType": "Forest Dweller",
|
|
175
|
-
"healthRecoveryRatePerHour": 0.25
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
"name": "Egghead",
|
|
179
|
-
"avatar": "🦄",
|
|
180
|
-
"healthLevel": 0.84,
|
|
181
|
-
"heroType": "Free Ranger",
|
|
182
|
-
"healthRecoveryRatePerHour": 0.22
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
"name": "Spouty",
|
|
186
|
-
"avatar": "🐳",
|
|
187
|
-
"healthLevel": 0.72,
|
|
188
|
-
"heroType": "Deep Sea Goer",
|
|
189
|
-
"healthRecoveryRatePerHour": 0.29
|
|
190
|
-
}
|
|
191
|
-
]
|
|
192
|
-
"""
|
|
193
|
-
|
|
194
|
-
extension EmojiRanger {
|
|
195
|
-
static let spook = EmojiRanger(
|
|
196
|
-
name: "Mr. Spook",
|
|
197
|
-
avatar: "💀",
|
|
198
|
-
healthLevel: 0.14,
|
|
199
|
-
heroType: "Calcium Lover",
|
|
200
|
-
healthRecoveryRatePerHour: 0.25,
|
|
201
|
-
url: URL(string: "game:///spook")!,
|
|
202
|
-
battleCode: URL(string: "game:///spook/battle")!,
|
|
203
|
-
level: 13,
|
|
204
|
-
exp: 2640,
|
|
205
|
-
bio: "Loves dancing, spooking, and playing their trumpet 🎺.")
|
|
206
|
-
|
|
207
|
-
static let cake = EmojiRanger(
|
|
208
|
-
name: "Cake",
|
|
209
|
-
avatar: "🎂",
|
|
210
|
-
healthLevel: 0.67,
|
|
211
|
-
heroType: "Literally Cake",
|
|
212
|
-
healthRecoveryRatePerHour: 0.22,
|
|
213
|
-
url: URL(string: "game:///cake")!,
|
|
214
|
-
battleCode: URL(string: "game:///cake/battle")!,
|
|
215
|
-
level: 15,
|
|
216
|
-
exp: 3121,
|
|
217
|
-
bio: """
|
|
218
|
-
• 1 cake mix
|
|
219
|
-
• 2 tbsp butter
|
|
220
|
-
• 4 large eggs
|
|
221
|
-
• 1 cup semi-sweet chocolate chips
|
|
222
|
-
""")
|
|
223
|
-
|
|
224
|
-
static let octo = EmojiRanger(
|
|
225
|
-
name: "Octo",
|
|
226
|
-
avatar: "🐙",
|
|
227
|
-
healthLevel: 0.83,
|
|
228
|
-
heroType: "Etymology Aficionado",
|
|
229
|
-
healthRecoveryRatePerHour: 0.29,
|
|
230
|
-
url: URL(string: "game:///octo")!,
|
|
231
|
-
battleCode: URL(string: "game:///octo/battle")!,
|
|
232
|
-
level: 43,
|
|
233
|
-
exp: 86_463,
|
|
234
|
-
bio: "Can give eight hugs simultaneously. They are best friends with Spouty.")
|
|
235
|
-
|
|
236
|
-
static let additionalHeros = [spook, cake, octo]
|
|
237
|
-
|
|
238
|
-
static let allHeros = EmojiRanger.availableHeros + EmojiRanger.additionalHeros
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
extension DateFormatter {
|
|
242
|
-
static let emojiFormatter: DateFormatter = {
|
|
243
|
-
let formatter = DateFormatter()
|
|
244
|
-
formatter.dateStyle = .short
|
|
245
|
-
formatter.timeStyle = .medium
|
|
246
|
-
return formatter
|
|
247
|
-
}()
|
|
248
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
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>INEnums</key>
|
|
6
|
-
<array/>
|
|
7
|
-
<key>INIntentDefinitionModelVersion</key>
|
|
8
|
-
<string>1.2</string>
|
|
9
|
-
<key>INIntentDefinitionNamespace</key>
|
|
10
|
-
<string>88xZPY</string>
|
|
11
|
-
<key>INIntentDefinitionSystemVersion</key>
|
|
12
|
-
<string>22D49</string>
|
|
13
|
-
<key>INIntentDefinitionToolsBuildVersion</key>
|
|
14
|
-
<string>14E222b</string>
|
|
15
|
-
<key>INIntentDefinitionToolsVersion</key>
|
|
16
|
-
<string>14.3</string>
|
|
17
|
-
<key>INIntents</key>
|
|
18
|
-
<array>
|
|
19
|
-
<dict>
|
|
20
|
-
<key>INIntentCategory</key>
|
|
21
|
-
<string>information</string>
|
|
22
|
-
<key>INIntentConfigurable</key>
|
|
23
|
-
<true/>
|
|
24
|
-
<key>INIntentDescription</key>
|
|
25
|
-
<string>Select Hero</string>
|
|
26
|
-
<key>INIntentDescriptionID</key>
|
|
27
|
-
<string>meoGMm</string>
|
|
28
|
-
<key>INIntentEligibleForWidgets</key>
|
|
29
|
-
<true/>
|
|
30
|
-
<key>INIntentIneligibleForSuggestions</key>
|
|
31
|
-
<true/>
|
|
32
|
-
<key>INIntentLastParameterTag</key>
|
|
33
|
-
<integer>12</integer>
|
|
34
|
-
<key>INIntentManagedParameterCombinations</key>
|
|
35
|
-
<dict>
|
|
36
|
-
<key>heroName</key>
|
|
37
|
-
<dict>
|
|
38
|
-
<key>INIntentParameterCombinationSupportsBackgroundExecution</key>
|
|
39
|
-
<true/>
|
|
40
|
-
<key>INIntentParameterCombinationUpdatesLinked</key>
|
|
41
|
-
<true/>
|
|
42
|
-
</dict>
|
|
43
|
-
</dict>
|
|
44
|
-
<key>INIntentName</key>
|
|
45
|
-
<string>EmojiRangerSelection</string>
|
|
46
|
-
<key>INIntentParameters</key>
|
|
47
|
-
<array>
|
|
48
|
-
<dict>
|
|
49
|
-
<key>INIntentParameterConfigurable</key>
|
|
50
|
-
<true/>
|
|
51
|
-
<key>INIntentParameterDisplayName</key>
|
|
52
|
-
<string>Selected Hero</string>
|
|
53
|
-
<key>INIntentParameterDisplayNameID</key>
|
|
54
|
-
<string>uHu7jj</string>
|
|
55
|
-
<key>INIntentParameterDisplayPriority</key>
|
|
56
|
-
<integer>1</integer>
|
|
57
|
-
<key>INIntentParameterMetadata</key>
|
|
58
|
-
<dict>
|
|
59
|
-
<key>INIntentParameterMetadataCapitalization</key>
|
|
60
|
-
<string>Sentences</string>
|
|
61
|
-
<key>INIntentParameterMetadataDefaultValueID</key>
|
|
62
|
-
<string>HhCW9t</string>
|
|
63
|
-
</dict>
|
|
64
|
-
<key>INIntentParameterName</key>
|
|
65
|
-
<string>heroName</string>
|
|
66
|
-
<key>INIntentParameterPromptDialogs</key>
|
|
67
|
-
<array>
|
|
68
|
-
<dict>
|
|
69
|
-
<key>INIntentParameterPromptDialogCustom</key>
|
|
70
|
-
<true/>
|
|
71
|
-
<key>INIntentParameterPromptDialogType</key>
|
|
72
|
-
<string>Configuration</string>
|
|
73
|
-
</dict>
|
|
74
|
-
<dict>
|
|
75
|
-
<key>INIntentParameterPromptDialogCustom</key>
|
|
76
|
-
<true/>
|
|
77
|
-
<key>INIntentParameterPromptDialogType</key>
|
|
78
|
-
<string>Primary</string>
|
|
79
|
-
</dict>
|
|
80
|
-
</array>
|
|
81
|
-
<key>INIntentParameterSupportsDynamicEnumeration</key>
|
|
82
|
-
<true/>
|
|
83
|
-
<key>INIntentParameterTag</key>
|
|
84
|
-
<integer>12</integer>
|
|
85
|
-
<key>INIntentParameterType</key>
|
|
86
|
-
<string>String</string>
|
|
87
|
-
</dict>
|
|
88
|
-
</array>
|
|
89
|
-
<key>INIntentResponse</key>
|
|
90
|
-
<dict>
|
|
91
|
-
<key>INIntentResponseCodes</key>
|
|
92
|
-
<array>
|
|
93
|
-
<dict>
|
|
94
|
-
<key>INIntentResponseCodeName</key>
|
|
95
|
-
<string>success</string>
|
|
96
|
-
<key>INIntentResponseCodeSuccess</key>
|
|
97
|
-
<true/>
|
|
98
|
-
</dict>
|
|
99
|
-
<dict>
|
|
100
|
-
<key>INIntentResponseCodeName</key>
|
|
101
|
-
<string>failure</string>
|
|
102
|
-
</dict>
|
|
103
|
-
</array>
|
|
104
|
-
</dict>
|
|
105
|
-
<key>INIntentTitle</key>
|
|
106
|
-
<string>Emoji Ranger Selection</string>
|
|
107
|
-
<key>INIntentTitleID</key>
|
|
108
|
-
<string>VT2aX1</string>
|
|
109
|
-
<key>INIntentType</key>
|
|
110
|
-
<string>Custom</string>
|
|
111
|
-
<key>INIntentVerb</key>
|
|
112
|
-
<string>View</string>
|
|
113
|
-
</dict>
|
|
114
|
-
</array>
|
|
115
|
-
<key>INTypes</key>
|
|
116
|
-
<array/>
|
|
117
|
-
</dict>
|
|
118
|
-
</plist>
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
See the LICENSE.txt file for this sample’s licensing information.
|
|
3
|
-
|
|
4
|
-
Abstract:
|
|
5
|
-
A widget that shows the avatar for a single hero.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import WidgetKit
|
|
9
|
-
import SwiftUI
|
|
10
|
-
|
|
11
|
-
struct SimpleEntry: TimelineEntry {
|
|
12
|
-
public let date: Date
|
|
13
|
-
let relevance: TimelineEntryRelevance?
|
|
14
|
-
let hero: EmojiRanger
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
struct PlaceholderView: View {
|
|
18
|
-
var body: some View {
|
|
19
|
-
EmojiRangerWidgetEntryView(entry: SimpleEntry(date: Date(), relevance: nil, hero: .spouty))
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
extension View {
|
|
24
|
-
func widgetBackground() -> some View {
|
|
25
|
-
if #available(iOSApplicationExtension 17.0, *) {
|
|
26
|
-
return containerBackground(for: .widget) {
|
|
27
|
-
Color.gameBackgroundColor
|
|
28
|
-
}
|
|
29
|
-
} else {
|
|
30
|
-
return background {
|
|
31
|
-
Color.gameBackgroundColor
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
struct EmojiRangerWidgetEntryView: View {
|
|
38
|
-
var entry: SimpleEntry
|
|
39
|
-
|
|
40
|
-
@Environment(\.widgetFamily) var family
|
|
41
|
-
|
|
42
|
-
@AppStorage("supercharged", store: UserDefaults(suiteName: EmojiRanger.appGroup))
|
|
43
|
-
var supercharged: Bool = EmojiRanger.herosAreSupercharged()
|
|
44
|
-
|
|
45
|
-
var body: some View {
|
|
46
|
-
switch family {
|
|
47
|
-
case .accessoryCircular:
|
|
48
|
-
ProgressView(timerInterval: entry.hero.injuryDate...entry.hero.fullHealthDate,
|
|
49
|
-
countsDown: false,
|
|
50
|
-
label: { Text(entry.hero.name) },
|
|
51
|
-
currentValueLabel: {
|
|
52
|
-
Avatar(hero: entry.hero, includeBackground: false)
|
|
53
|
-
})
|
|
54
|
-
.progressViewStyle(.circular)
|
|
55
|
-
|
|
56
|
-
case .accessoryRectangular:
|
|
57
|
-
HStack(alignment: .center, spacing: 0) {
|
|
58
|
-
VStack(alignment: .leading) {
|
|
59
|
-
Text(entry.hero.name)
|
|
60
|
-
.font(.headline)
|
|
61
|
-
.widgetAccentable()
|
|
62
|
-
Text("Level \(entry.hero.level)")
|
|
63
|
-
Text(entry.hero.fullHealthDate, style: .timer)
|
|
64
|
-
}.frame(maxWidth: .infinity, alignment: .leading)
|
|
65
|
-
Avatar(hero: entry.hero, includeBackground: false)
|
|
66
|
-
}
|
|
67
|
-
.widgetBackground()
|
|
68
|
-
|
|
69
|
-
case .accessoryInline:
|
|
70
|
-
ViewThatFits {
|
|
71
|
-
Text("\(entry.hero.name) is healing, ready in \(entry.hero.fullHealthDate, style: .relative)")
|
|
72
|
-
Text("\(entry.hero.name) ready in \(entry.hero.fullHealthDate, style: .relative)")
|
|
73
|
-
Text("\(entry.hero.name) \(entry.hero.fullHealthDate, style: .timer)")
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
case .systemSmall:
|
|
77
|
-
AvatarView(entry.hero)
|
|
78
|
-
.widgetURL(entry.hero.url)
|
|
79
|
-
.foregroundColor(.white)
|
|
80
|
-
.widgetBackground()
|
|
81
|
-
.widgetURL(entry.hero.url)
|
|
82
|
-
|
|
83
|
-
case .systemLarge:
|
|
84
|
-
VStack {
|
|
85
|
-
HStack(alignment: .top) {
|
|
86
|
-
AvatarView(entry.hero)
|
|
87
|
-
.foregroundColor(.white)
|
|
88
|
-
Text(entry.hero.bio)
|
|
89
|
-
.foregroundColor(.white)
|
|
90
|
-
}
|
|
91
|
-
.padding()
|
|
92
|
-
#if os(iOS)
|
|
93
|
-
if #available(iOSApplicationExtension 17.0, *) {
|
|
94
|
-
Button(intent: SuperCharge()) {
|
|
95
|
-
Text("⚡️")
|
|
96
|
-
.lineLimit(1)
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
#endif
|
|
100
|
-
}
|
|
101
|
-
.widgetBackground()
|
|
102
|
-
.widgetURL(entry.hero.url)
|
|
103
|
-
case .systemMedium:
|
|
104
|
-
HStack(alignment: .top) {
|
|
105
|
-
AvatarView(entry.hero)
|
|
106
|
-
.foregroundColor(.white)
|
|
107
|
-
Text(entry.hero.bio)
|
|
108
|
-
.foregroundColor(.white)
|
|
109
|
-
}
|
|
110
|
-
.widgetBackground()
|
|
111
|
-
.widgetURL(entry.hero.url)
|
|
112
|
-
default:
|
|
113
|
-
AvatarView(entry.hero)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
struct EmojiRangerWidget: Widget {
|
|
120
|
-
|
|
121
|
-
func makeWidgetConfiguration() -> some WidgetConfiguration {
|
|
122
|
-
#if os(watchOS)
|
|
123
|
-
return IntentConfiguration(kind: EmojiRanger.EmojiRangerWidgetKind,
|
|
124
|
-
intent: EmojiRangerSelectionIntent.self,
|
|
125
|
-
provider: SiriKitWatchIntentProvider()) { entry in
|
|
126
|
-
EmojiRangerWidgetEntryView(entry: entry)
|
|
127
|
-
}
|
|
128
|
-
.supportedFamilies(supportedFamilies)
|
|
129
|
-
#else
|
|
130
|
-
if #available(iOS 17.0, macOS 14.0, *) {
|
|
131
|
-
return AppIntentConfiguration(kind: EmojiRanger.EmojiRangerWidgetKind,
|
|
132
|
-
intent: EmojiRangerSelection.self,
|
|
133
|
-
provider: AppIntentProvider()) { entry in
|
|
134
|
-
EmojiRangerWidgetEntryView(entry: entry)
|
|
135
|
-
}
|
|
136
|
-
.supportedFamilies(supportedFamilies)
|
|
137
|
-
} else {
|
|
138
|
-
return IntentConfiguration(kind: EmojiRanger.EmojiRangerWidgetKind,
|
|
139
|
-
intent: EmojiRangerSelectionIntent.self,
|
|
140
|
-
provider: SiriKitIntentProvider()) { entry in
|
|
141
|
-
EmojiRangerWidgetEntryView(entry: entry)
|
|
142
|
-
}
|
|
143
|
-
.supportedFamilies(supportedFamilies)
|
|
144
|
-
}
|
|
145
|
-
#endif
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
private var supportedFamilies: [WidgetFamily] {
|
|
149
|
-
#if os(watchOS)
|
|
150
|
-
[.accessoryCircular,
|
|
151
|
-
.accessoryRectangular, .accessoryInline]
|
|
152
|
-
#else
|
|
153
|
-
[.accessoryCircular,
|
|
154
|
-
.accessoryRectangular, .accessoryInline,
|
|
155
|
-
.systemSmall, .systemMedium, .systemLarge]
|
|
156
|
-
#endif
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
public var body: some WidgetConfiguration {
|
|
160
|
-
makeWidgetConfiguration()
|
|
161
|
-
.configurationDisplayName("Ranger Detail")
|
|
162
|
-
.description("See your favorite ranger.")
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
struct Widget_Previews: PreviewProvider {
|
|
167
|
-
static var previews: some View {
|
|
168
|
-
Group {
|
|
169
|
-
EmojiRangerWidgetEntryView(entry: SimpleEntry(date: Date(), relevance: nil, hero: .spouty))
|
|
170
|
-
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
|
171
|
-
.previewDisplayName("Circular")
|
|
172
|
-
|
|
173
|
-
EmojiRangerWidgetEntryView(entry: SimpleEntry(date: Date(), relevance: nil, hero: .spouty))
|
|
174
|
-
.previewContext(WidgetPreviewContext(family: .accessoryRectangular))
|
|
175
|
-
.previewDisplayName("Rectangular")
|
|
176
|
-
EmojiRangerWidgetEntryView(entry: SimpleEntry(date: Date(), relevance: nil, hero: .spouty))
|
|
177
|
-
.previewContext(WidgetPreviewContext(family: .accessoryInline))
|
|
178
|
-
.previewDisplayName("Inline")
|
|
179
|
-
|
|
180
|
-
#if os(iOS)
|
|
181
|
-
|
|
182
|
-
EmojiRangerWidgetEntryView(entry: SimpleEntry(date: Date(), relevance: nil, hero: .spouty))
|
|
183
|
-
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
|
184
|
-
EmojiRangerWidgetEntryView(entry: SimpleEntry(date: Date(), relevance: nil, hero: .spouty))
|
|
185
|
-
.previewContext(WidgetPreviewContext(family: .systemMedium))
|
|
186
|
-
#endif
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
See the LICENSE.txt file for this sample’s licensing information.
|
|
3
|
-
|
|
4
|
-
Abstract:
|
|
5
|
-
The widget bundle.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import WidgetKit
|
|
9
|
-
import SwiftUI
|
|
10
|
-
|
|
11
|
-
@main
|
|
12
|
-
struct EmojiRangersWidgetBundle: WidgetBundle {
|
|
13
|
-
var body: some Widget {
|
|
14
|
-
EmojiRangerWidget()
|
|
15
|
-
LeaderboardWidget()
|
|
16
|
-
#if canImport(ActivityKit)
|
|
17
|
-
AdventureActivityConfiguration()
|
|
18
|
-
#endif
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
See the LICENSE.txt file for this sample’s licensing information.
|
|
3
|
-
|
|
4
|
-
Abstract:
|
|
5
|
-
A protocol that defines methods to load images.
|
|
6
|
-
*/
|
|
7
|
-
import Foundation
|
|
8
|
-
|
|
9
|
-
class ImageURLProtocol: URLProtocol {
|
|
10
|
-
|
|
11
|
-
var cancelledOrComplete: Bool = false
|
|
12
|
-
var block: DispatchWorkItem!
|
|
13
|
-
|
|
14
|
-
private static let queue = DispatchSerialQueue(label: "com.apple.imageLoaderURLProtocol")
|
|
15
|
-
|
|
16
|
-
override class func canInit(with request: URLRequest) -> Bool {
|
|
17
|
-
return true
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
|
|
21
|
-
return request
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
class override func requestIsCacheEquivalent(_ aRequest: URLRequest, to bRequest: URLRequest) -> Bool {
|
|
25
|
-
return false
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
final override func startLoading() {
|
|
29
|
-
guard let reqURL = request.url, let urlClient = client else {
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
block = DispatchWorkItem(block: {
|
|
34
|
-
if self.cancelledOrComplete == false {
|
|
35
|
-
let fileURL = URL(fileURLWithPath: reqURL.path)
|
|
36
|
-
|
|
37
|
-
if let data = try? Data(contentsOf: fileURL) {
|
|
38
|
-
urlClient.urlProtocol(self, didLoad: data)
|
|
39
|
-
urlClient.urlProtocolDidFinishLoading(self)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
self.cancelledOrComplete = true
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
ImageURLProtocol.queue.asyncAfter(deadline: DispatchTime(uptimeNanoseconds: 500 * NSEC_PER_MSEC), execute: block)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
final override func stopLoading() {
|
|
49
|
-
ImageURLProtocol.queue.async {
|
|
50
|
-
if self.cancelledOrComplete == false, let cancelBlock = self.block {
|
|
51
|
-
cancelBlock.cancel()
|
|
52
|
-
|
|
53
|
-
self.cancelledOrComplete = true
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static func urlSession() -> URLSession {
|
|
59
|
-
let config = URLSessionConfiguration.ephemeral
|
|
60
|
-
|
|
61
|
-
config.protocolClasses = [ImageURLProtocol.classForCoder()]
|
|
62
|
-
|
|
63
|
-
return URLSession(configuration: config)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
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>NSExtension</key>
|
|
6
|
-
<dict>
|
|
7
|
-
<key>NSExtensionPointIdentifier</key>
|
|
8
|
-
<string>com.apple.widgetkit-extension</string>
|
|
9
|
-
</dict>
|
|
10
|
-
</dict>
|
|
11
|
-
</plist>
|