mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-17 02:33:27 +01:00
[AltWidget] Refactors previous widgets to use AppsTimelineProvider
This commit is contained in:
@@ -382,7 +382,6 @@
|
|||||||
D57F2C9126E0070200B9FA39 /* EnableJITOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57F2C9026E0070200B9FA39 /* EnableJITOperation.swift */; };
|
D57F2C9126E0070200B9FA39 /* EnableJITOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57F2C9026E0070200B9FA39 /* EnableJITOperation.swift */; };
|
||||||
D57F2C9426E01BC700B9FA39 /* UIDevice+Vibration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57F2C9326E01BC700B9FA39 /* UIDevice+Vibration.swift */; };
|
D57F2C9426E01BC700B9FA39 /* UIDevice+Vibration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57F2C9326E01BC700B9FA39 /* UIDevice+Vibration.swift */; };
|
||||||
D57FE84428C7DB7100216002 /* ErrorLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57FE84328C7DB7100216002 /* ErrorLogViewController.swift */; };
|
D57FE84428C7DB7100216002 /* ErrorLogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57FE84328C7DB7100216002 /* ErrorLogViewController.swift */; };
|
||||||
D586222F2AA1161700A493E1 /* Provider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D586222D2AA115D000A493E1 /* Provider.swift */; };
|
|
||||||
D586D39B28EF58B0000E101F /* AltTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D586D39A28EF58B0000E101F /* AltTests.swift */; };
|
D586D39B28EF58B0000E101F /* AltTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D586D39A28EF58B0000E101F /* AltTests.swift */; };
|
||||||
D58916FE28C7C55C00E39C8B /* LoggedError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58916FD28C7C55C00E39C8B /* LoggedError.swift */; };
|
D58916FE28C7C55C00E39C8B /* LoggedError.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58916FD28C7C55C00E39C8B /* LoggedError.swift */; };
|
||||||
D5893F802A1419E800E767CD /* NSManagedObjectContext+Conveniences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5893F7E2A14183200E767CD /* NSManagedObjectContext+Conveniences.swift */; };
|
D5893F802A1419E800E767CD /* NSManagedObjectContext+Conveniences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5893F7E2A14183200E767CD /* NSManagedObjectContext+Conveniences.swift */; };
|
||||||
@@ -920,7 +919,6 @@
|
|||||||
D57F2C9326E01BC700B9FA39 /* UIDevice+Vibration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+Vibration.swift"; sourceTree = "<group>"; };
|
D57F2C9326E01BC700B9FA39 /* UIDevice+Vibration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+Vibration.swift"; sourceTree = "<group>"; };
|
||||||
D57FE84328C7DB7100216002 /* ErrorLogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorLogViewController.swift; sourceTree = "<group>"; };
|
D57FE84328C7DB7100216002 /* ErrorLogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorLogViewController.swift; sourceTree = "<group>"; };
|
||||||
D581822C2A218A140087965B /* AltStore 13.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AltStore 13.xcdatamodel"; sourceTree = "<group>"; };
|
D581822C2A218A140087965B /* AltStore 13.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AltStore 13.xcdatamodel"; sourceTree = "<group>"; };
|
||||||
D586222D2AA115D000A493E1 /* Provider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Provider.swift; sourceTree = "<group>"; };
|
|
||||||
D586D39828EF58B0000E101F /* AltTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AltTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
D586D39828EF58B0000E101F /* AltTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AltTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D586D39A28EF58B0000E101F /* AltTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AltTests.swift; sourceTree = "<group>"; };
|
D586D39A28EF58B0000E101F /* AltTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AltTests.swift; sourceTree = "<group>"; };
|
||||||
D58916FD28C7C55C00E39C8B /* LoggedError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedError.swift; sourceTree = "<group>"; };
|
D58916FD28C7C55C00E39C8B /* LoggedError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedError.swift; sourceTree = "<group>"; };
|
||||||
@@ -1551,7 +1549,6 @@
|
|||||||
children = (
|
children = (
|
||||||
BF8B17F0250AC62400F8157F /* AltWidgetExtension.entitlements */,
|
BF8B17F0250AC62400F8157F /* AltWidgetExtension.entitlements */,
|
||||||
D5FD4EC42A952EAD0097BEE8 /* AltWidgetBundle.swift */,
|
D5FD4EC42A952EAD0097BEE8 /* AltWidgetBundle.swift */,
|
||||||
D586222D2AA115D000A493E1 /* Provider.swift */,
|
|
||||||
D577AB7A2A967DF5007FE952 /* AppsTimelineProvider.swift */,
|
D577AB7A2A967DF5007FE952 /* AppsTimelineProvider.swift */,
|
||||||
D50C29F22A8ECD71009AB488 /* Widgets */,
|
D50C29F22A8ECD71009AB488 /* Widgets */,
|
||||||
D51AF9752A97D29100471312 /* Model */,
|
D51AF9752A97D29100471312 /* Model */,
|
||||||
@@ -2867,7 +2864,6 @@
|
|||||||
BF98917E250AAC4F002ACF50 /* Countdown.swift in Sources */,
|
BF98917E250AAC4F002ACF50 /* Countdown.swift in Sources */,
|
||||||
D5151BE22A90363300C96F28 /* RefreshAllAppsWidgetIntent.swift in Sources */,
|
D5151BE22A90363300C96F28 /* RefreshAllAppsWidgetIntent.swift in Sources */,
|
||||||
D5FD4EC92A9530C00097BEE8 /* AppSnapshot.swift in Sources */,
|
D5FD4EC92A9530C00097BEE8 /* AppSnapshot.swift in Sources */,
|
||||||
D586222F2AA1161700A493E1 /* Provider.swift in Sources */,
|
|
||||||
D5151BE72A90395400C96F28 /* View+AltWidget.swift in Sources */,
|
D5151BE72A90395400C96F28 /* View+AltWidget.swift in Sources */,
|
||||||
BF98917F250AAC4F002ACF50 /* LockScreenWidget.swift in Sources */,
|
BF98917F250AAC4F002ACF50 /* LockScreenWidget.swift in Sources */,
|
||||||
D5FD4EC52A952EAD0097BEE8 /* AltWidgetBundle.swift in Sources */,
|
D5FD4EC52A952EAD0097BEE8 /* AltWidgetBundle.swift in Sources */,
|
||||||
|
|||||||
@@ -200,3 +200,28 @@ extension AppsTimelineProvider: TimelineProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension AppsTimelineProvider: IntentTimelineProvider
|
||||||
|
{
|
||||||
|
typealias Intent = ViewAppIntent
|
||||||
|
|
||||||
|
func getSnapshot(for intent: Intent, in context: Context, completion: @escaping (AppsEntry) -> Void)
|
||||||
|
{
|
||||||
|
Task<Void, Never> {
|
||||||
|
let bundleIDs = [intent.identifier ?? StoreApp.altstoreAppID]
|
||||||
|
|
||||||
|
let snapshot = await self.snapshot(for: bundleIDs)
|
||||||
|
completion(snapshot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTimeline(for intent: Intent, in context: Context, completion: @escaping (Timeline<AppsEntry>) -> Void)
|
||||||
|
{
|
||||||
|
Task<Void, Never> {
|
||||||
|
let bundleIDs = [intent.identifier ?? StoreApp.altstoreAppID]
|
||||||
|
|
||||||
|
let timeline = await self.timeline(for: bundleIDs)
|
||||||
|
completion(timeline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,144 +0,0 @@
|
|||||||
//
|
|
||||||
// Provider.swift
|
|
||||||
// AltStore
|
|
||||||
//
|
|
||||||
// Created by Riley Testut on 6/26/20.
|
|
||||||
// Copyright © 2020 Riley Testut. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import WidgetKit
|
|
||||||
import CoreData
|
|
||||||
|
|
||||||
import AltStoreCore
|
|
||||||
import AltSign
|
|
||||||
|
|
||||||
struct AppEntry: TimelineEntry
|
|
||||||
{
|
|
||||||
var date: Date
|
|
||||||
var relevance: TimelineEntryRelevance?
|
|
||||||
|
|
||||||
var app: AppSnapshot?
|
|
||||||
var isPlaceholder: Bool = false
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Provider: IntentTimelineProvider
|
|
||||||
{
|
|
||||||
typealias Intent = ViewAppIntent
|
|
||||||
typealias Entry = AppEntry
|
|
||||||
|
|
||||||
func placeholder(in context: Context) -> AppEntry
|
|
||||||
{
|
|
||||||
return AppEntry(date: Date(), app: nil, isPlaceholder: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSnapshot(for configuration: ViewAppIntent, in context: Context, completion: @escaping (AppEntry) -> Void)
|
|
||||||
{
|
|
||||||
self.prepare { (result) in
|
|
||||||
do
|
|
||||||
{
|
|
||||||
let context = try result.get()
|
|
||||||
let snapshot = InstalledApp.fetchAltStore(in: context).map(AppSnapshot.init)
|
|
||||||
|
|
||||||
let entry = AppEntry(date: Date(), app: snapshot)
|
|
||||||
completion(entry)
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
print("Error preparing widget snapshot:", error)
|
|
||||||
|
|
||||||
let entry = AppEntry(date: Date(), app: nil)
|
|
||||||
completion(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTimeline(for configuration: ViewAppIntent, in context: Context, completion: @escaping (Timeline<AppEntry>) -> Void) {
|
|
||||||
self.prepare { (result) in
|
|
||||||
autoreleasepool {
|
|
||||||
do
|
|
||||||
{
|
|
||||||
let context = try result.get()
|
|
||||||
|
|
||||||
let installedApp: InstalledApp?
|
|
||||||
|
|
||||||
if let identifier = configuration.app?.identifier
|
|
||||||
{
|
|
||||||
let app = InstalledApp.first(satisfying: NSPredicate(format: "%K == %@", #keyPath(InstalledApp.bundleIdentifier), identifier),
|
|
||||||
in: context)
|
|
||||||
installedApp = app
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
installedApp = InstalledApp.fetchAltStore(in: context)
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let snapshot = installedApp.map(AppSnapshot.init) else { throw ALTError(.invalidApp) }
|
|
||||||
|
|
||||||
let currentDate = Calendar.current.startOfDay(for: Date())
|
|
||||||
let numberOfDays = snapshot.expirationDate.numberOfCalendarDays(since: currentDate)
|
|
||||||
|
|
||||||
// Generate a timeline consisting of one entry per day.
|
|
||||||
var entries: [AppEntry] = []
|
|
||||||
|
|
||||||
switch numberOfDays
|
|
||||||
{
|
|
||||||
case ..<0:
|
|
||||||
let entry = AppEntry(date: currentDate, relevance: TimelineEntryRelevance(score: 0.0), app: snapshot)
|
|
||||||
entries.append(entry)
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
let entry = AppEntry(date: currentDate, relevance: TimelineEntryRelevance(score: 1.0), app: snapshot)
|
|
||||||
entries.append(entry)
|
|
||||||
|
|
||||||
default:
|
|
||||||
// To reduce memory consumption, we only generate entries for the next week. This includes:
|
|
||||||
// * 1 for each day the app is valid (up to 7)
|
|
||||||
// * 1 "0 days remaining"
|
|
||||||
// * 1 "Expired"
|
|
||||||
let numberOfEntries = min(numberOfDays, 7) + 2
|
|
||||||
|
|
||||||
let appEntries = (0 ..< numberOfEntries).map { (dayOffset) -> AppEntry in
|
|
||||||
let entryDate = Calendar.current.date(byAdding: .day, value: dayOffset, to: currentDate) ?? currentDate.addingTimeInterval(Double(dayOffset) * 60 * 60 * 24)
|
|
||||||
|
|
||||||
let daysSinceRefresh = entryDate.numberOfCalendarDays(since: snapshot.refreshedDate)
|
|
||||||
let totalNumberOfDays = snapshot.expirationDate.numberOfCalendarDays(since: snapshot.refreshedDate)
|
|
||||||
|
|
||||||
let score = (entryDate <= snapshot.expirationDate) ? Float(daysSinceRefresh + 1) / Float(totalNumberOfDays + 1) : 0 // Expired apps have a score of 0.
|
|
||||||
let entry = AppEntry(date: entryDate, relevance: TimelineEntryRelevance(score: score), app: snapshot)
|
|
||||||
return entry
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.append(contentsOf: appEntries)
|
|
||||||
}
|
|
||||||
|
|
||||||
let timeline = Timeline(entries: entries, policy: .atEnd)
|
|
||||||
completion(timeline)
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
print("Error preparing widget timeline:", error)
|
|
||||||
|
|
||||||
let entry = AppEntry(date: Date(), app: nil)
|
|
||||||
let timeline = Timeline(entries: [entry], policy: .atEnd)
|
|
||||||
completion(timeline)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func prepare(completion: @escaping (Result<NSManagedObjectContext, Error>) -> Void)
|
|
||||||
{
|
|
||||||
DatabaseManager.shared.start { (error) in
|
|
||||||
if let error = error
|
|
||||||
{
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DatabaseManager.shared.viewContext.perform {
|
|
||||||
completion(.success(DatabaseManager.shared.viewContext))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,7 @@ struct AppDetailWidget: Widget
|
|||||||
public var body: some WidgetConfiguration {
|
public var body: some WidgetConfiguration {
|
||||||
let configuration = IntentConfiguration(kind: kind,
|
let configuration = IntentConfiguration(kind: kind,
|
||||||
intent: ViewAppIntent.self,
|
intent: ViewAppIntent.self,
|
||||||
provider: Provider()) { (entry) in
|
provider: AppsTimelineProvider()) { (entry) in
|
||||||
AppDetailWidgetView(entry: entry)
|
AppDetailWidgetView(entry: entry)
|
||||||
}
|
}
|
||||||
.supportedFamilies([.systemSmall])
|
.supportedFamilies([.systemSmall])
|
||||||
@@ -39,11 +39,11 @@ struct AppDetailWidget: Widget
|
|||||||
|
|
||||||
private struct AppDetailWidgetView: View
|
private struct AppDetailWidgetView: View
|
||||||
{
|
{
|
||||||
var entry: AppEntry
|
var entry: AppsEntry
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if let app = self.entry.app
|
if let app = self.entry.apps.first
|
||||||
{
|
{
|
||||||
let daysRemaining = app.expirationDate.numberOfCalendarDays(since: self.entry.date)
|
let daysRemaining = app.expirationDate.numberOfCalendarDays(since: self.entry.date)
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ private struct AppDetailWidgetView: View
|
|||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.widgetBackground(backgroundView(icon: entry.app?.icon, tintColor: entry.app?.tintColor))
|
.widgetBackground(backgroundView(icon: entry.apps.first?.icon, tintColor: entry.apps.first?.tintColor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,19 +202,19 @@ struct WidgetView_Previews: PreviewProvider {
|
|||||||
icon: UIImage(named: "Delta"))
|
icon: UIImage(named: "Delta"))
|
||||||
|
|
||||||
return Group {
|
return Group {
|
||||||
AppDetailWidgetView(entry: AppEntry(date: Date(), app: altstore))
|
AppDetailWidgetView(entry: AppsEntry(date: Date(), apps: [altstore]))
|
||||||
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||||
|
|
||||||
AppDetailWidgetView(entry: AppEntry(date: Date(), app: delta))
|
AppDetailWidgetView(entry: AppsEntry(date: Date(), apps: [delta]))
|
||||||
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||||
|
|
||||||
AppDetailWidgetView(entry: AppEntry(date: Date(), app: expiredDelta))
|
AppDetailWidgetView(entry: AppsEntry(date: Date(), apps: [expiredDelta]))
|
||||||
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||||
|
|
||||||
AppDetailWidgetView(entry: AppEntry(date: Date(), app: nil))
|
AppDetailWidgetView(entry: AppsEntry(date: Date(), apps: []))
|
||||||
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||||
|
|
||||||
AppDetailWidgetView(entry: AppEntry(date: Date(), app: nil, isPlaceholder: true))
|
AppDetailWidgetView(entry: AppsEntry(date: Date(), apps: [], isPlaceholder: true))
|
||||||
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ struct TextLockScreenWidget: Widget
|
|||||||
{
|
{
|
||||||
return IntentConfiguration(kind: kind,
|
return IntentConfiguration(kind: kind,
|
||||||
intent: ViewAppIntent.self,
|
intent: ViewAppIntent.self,
|
||||||
provider: Provider()) { (entry) in
|
provider: AppsTimelineProvider()) { (entry) in
|
||||||
ComplicationView(entry: entry, style: .text)
|
ComplicationView(entry: entry, style: .text)
|
||||||
}
|
}
|
||||||
.supportedFamilies([.accessoryCircular])
|
.supportedFamilies([.accessoryCircular])
|
||||||
@@ -43,7 +43,7 @@ struct IconLockScreenWidget: Widget
|
|||||||
{
|
{
|
||||||
return IntentConfiguration(kind: kind,
|
return IntentConfiguration(kind: kind,
|
||||||
intent: ViewAppIntent.self,
|
intent: ViewAppIntent.self,
|
||||||
provider: Provider()) { (entry) in
|
provider: AppsTimelineProvider()) { (entry) in
|
||||||
ComplicationView(entry: entry, style: .icon)
|
ComplicationView(entry: entry, style: .icon)
|
||||||
}
|
}
|
||||||
.supportedFamilies([.accessoryCircular])
|
.supportedFamilies([.accessoryCircular])
|
||||||
@@ -70,12 +70,12 @@ extension ComplicationView
|
|||||||
@available(iOS 16, *)
|
@available(iOS 16, *)
|
||||||
private struct ComplicationView: View
|
private struct ComplicationView: View
|
||||||
{
|
{
|
||||||
let entry: AppEntry
|
let entry: AppsEntry
|
||||||
let style: Style
|
let style: Style
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let refreshedDate = self.entry.app?.refreshedDate ?? .now
|
let refreshedDate = self.entry.apps.first?.refreshedDate ?? .now
|
||||||
let expirationDate = self.entry.app?.expirationDate ?? .now
|
let expirationDate = self.entry.apps.first?.expirationDate ?? .now
|
||||||
|
|
||||||
let totalDays = expirationDate.numberOfCalendarDays(since: refreshedDate)
|
let totalDays = expirationDate.numberOfCalendarDays(since: refreshedDate)
|
||||||
let daysRemaining = expirationDate.numberOfCalendarDays(since: self.entry.date)
|
let daysRemaining = expirationDate.numberOfCalendarDays(since: self.entry.date)
|
||||||
@@ -159,22 +159,22 @@ struct ComplicationView_Previews: PreviewProvider {
|
|||||||
icon: UIImage(named: "AltStore"))
|
icon: UIImage(named: "AltStore"))
|
||||||
|
|
||||||
return Group {
|
return Group {
|
||||||
ComplicationView(entry: AppEntry(date: Date(), app: weekAltstore), style: .icon)
|
ComplicationView(entry: AppsEntry(date: Date(), apps: [weekAltstore]), style: .icon)
|
||||||
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
||||||
|
|
||||||
ComplicationView(entry: AppEntry(date: expiredDate, app: weekAltstore), style: .icon)
|
ComplicationView(entry: AppsEntry(date: expiredDate, apps: [weekAltstore]), style: .icon)
|
||||||
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
||||||
|
|
||||||
ComplicationView(entry: AppEntry(date: longRefreshedDate, app: yearAltstore), style: .icon)
|
ComplicationView(entry: AppsEntry(date: longRefreshedDate, apps: [yearAltstore]), style: .icon)
|
||||||
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
||||||
|
|
||||||
ComplicationView(entry: AppEntry(date: Date(), app: weekAltstore), style: .text)
|
ComplicationView(entry: AppsEntry(date: Date(), apps: [weekAltstore]), style: .text)
|
||||||
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
||||||
|
|
||||||
ComplicationView(entry: AppEntry(date: expiredDate, app: weekAltstore), style: .text)
|
ComplicationView(entry: AppsEntry(date: expiredDate, apps: [weekAltstore]), style: .text)
|
||||||
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
||||||
|
|
||||||
ComplicationView(entry: AppEntry(date: longRefreshedDate, app: yearAltstore), style: .text)
|
ComplicationView(entry: AppsEntry(date: longRefreshedDate, apps: [yearAltstore]), style: .text)
|
||||||
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user