mirror of
https://github.com/StikDebug/StikDebug.git
synced 2026-10-15 20:10:30 +00:00
Remove widget extension, keep the keep-alive banner in-app only
Drops the StikDebugWidgets extension target, the shared ActivityAttributes, and the KeepAliveLiveActivity controller — no Dynamic Island / Lock Screen presentation. The banner stays as the existing in-app overlay in HomeView, now also shown when holding an app from the "Other" tab. project.pbxproj, Info.plist, and AppBootstrapper.swift are back to their pre-widget state. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EpCxAimrBo9RA8v6BxSEXT
This commit is contained in:
parent
23e8052c7b
commit
e4f02100ee
9 changed files with 1 additions and 428 deletions
|
|
@ -9,7 +9,6 @@
|
|||
/* Begin PBXBuildFile section */
|
||||
68D569BE2E1B415700A5BA36 /* CodeEditorView in Frameworks */ = {isa = PBXBuildFile; productRef = 68D569BD2E1B415700A5BA36 /* CodeEditorView */; };
|
||||
68D569C02E1B415700A5BA36 /* LanguageSupport in Frameworks */ = {isa = PBXBuildFile; productRef = 68D569BF2E1B415700A5BA36 /* LanguageSupport */; };
|
||||
F00DCAFE000000000000E00B /* StikDebugWidgets.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = F00DCAFE000000000000E002 /* StikDebugWidgets.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
|
@ -27,13 +26,6 @@
|
|||
remoteGlobalIDString = DC6F1D362D94EADD0071B2B6;
|
||||
remoteInfo = StikDebug;
|
||||
};
|
||||
F00DCAFE000000000000E00D /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DC6F1D2F2D94EADD0071B2B6 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F00DCAFE000000000000E001;
|
||||
remoteInfo = StikDebugWidgets;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
|
|
@ -43,7 +35,6 @@
|
|||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
F00DCAFE000000000000E00B /* StikDebugWidgets.appex in Embed Foundation Extensions */,
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -56,7 +47,6 @@
|
|||
DC6F1D372D94EADD0071B2B6 /* StikDebug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StikDebug.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DC6F1D482D94EADF0071B2B6 /* StikDebugTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StikDebugTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DC6F1D522D94EADF0071B2B6 /* StikDebugUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StikDebugUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F00DCAFE000000000000E002 /* StikDebugWidgets.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = StikDebugWidgets.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
|
|
@ -67,13 +57,6 @@
|
|||
);
|
||||
target = DC6F1D362D94EADD0071B2B6 /* StikDebug */;
|
||||
};
|
||||
F00DCAFE000000000000E00E /* Exceptions for "StikDebugWidgets" folder in "StikDebugWidgets" target */ = {
|
||||
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||
membershipExceptions = (
|
||||
Info.plist,
|
||||
);
|
||||
target = F00DCAFE000000000000E001 /* StikDebugWidgets */;
|
||||
};
|
||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
|
|
@ -85,19 +68,6 @@
|
|||
path = StikDebug;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F00DCAFE000000000000E006 /* StikDebugWidgets */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
F00DCAFE000000000000E00E /* Exceptions for "StikDebugWidgets" folder in "StikDebugWidgets" target */,
|
||||
);
|
||||
path = StikDebugWidgets;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F00DCAFE000000000000E007 /* StikDebugShared */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
path = StikDebugShared;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DC6F1D4B2D94EADF0071B2B6 /* StikDebugTests */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
path = StikDebugTests;
|
||||
|
|
@ -134,13 +104,6 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F00DCAFE000000000000E004 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
|
|
@ -148,8 +111,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DC6F1D392D94EADD0071B2B6 /* StikDebug */,
|
||||
F00DCAFE000000000000E007 /* StikDebugShared */,
|
||||
F00DCAFE000000000000E006 /* StikDebugWidgets */,
|
||||
DC6F1D4B2D94EADF0071B2B6 /* StikDebugTests */,
|
||||
DC6F1D552D94EADF0071B2B6 /* StikDebugUITests */,
|
||||
DC6F1D752D94EB620071B2B6 /* Frameworks */,
|
||||
|
|
@ -163,7 +124,6 @@
|
|||
DC6F1D372D94EADD0071B2B6 /* StikDebug.app */,
|
||||
DC6F1D482D94EADF0071B2B6 /* StikDebugTests.xctest */,
|
||||
DC6F1D522D94EADF0071B2B6 /* StikDebugUITests.xctest */,
|
||||
F00DCAFE000000000000E002 /* StikDebugWidgets.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -192,11 +152,9 @@
|
|||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
F00DCAFE000000000000E00C /* PBXTargetDependency */,
|
||||
);
|
||||
fileSystemSynchronizedGroups = (
|
||||
DC6F1D392D94EADD0071B2B6 /* StikDebug */,
|
||||
F00DCAFE000000000000E007 /* StikDebugShared */,
|
||||
);
|
||||
name = StikDebug;
|
||||
packageProductDependencies = (
|
||||
|
|
@ -207,29 +165,6 @@
|
|||
productReference = DC6F1D372D94EADD0071B2B6 /* StikDebug.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
F00DCAFE000000000000E001 /* StikDebugWidgets */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F00DCAFE000000000000E008 /* Build configuration list for PBXNativeTarget "StikDebugWidgets" */;
|
||||
buildPhases = (
|
||||
F00DCAFE000000000000E003 /* Sources */,
|
||||
F00DCAFE000000000000E004 /* Frameworks */,
|
||||
F00DCAFE000000000000E005 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
fileSystemSynchronizedGroups = (
|
||||
F00DCAFE000000000000E006 /* StikDebugWidgets */,
|
||||
F00DCAFE000000000000E007 /* StikDebugShared */,
|
||||
);
|
||||
name = StikDebugWidgets;
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = StikDebugWidgets;
|
||||
productReference = F00DCAFE000000000000E002 /* StikDebugWidgets.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
DC6F1D472D94EADF0071B2B6 /* StikDebugTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DC6F1D5F2D94EADF0071B2B6 /* Build configuration list for PBXNativeTarget "StikDebugTests" */;
|
||||
|
|
@ -298,9 +233,6 @@
|
|||
CreatedOnToolsVersion = 16.2;
|
||||
TestTargetID = DC6F1D362D94EADD0071B2B6;
|
||||
};
|
||||
F00DCAFE000000000000E001 = {
|
||||
CreatedOnToolsVersion = 16.2;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = DC6F1D322D94EADD0071B2B6 /* Build configuration list for PBXProject "StikDebug" */;
|
||||
|
|
@ -323,7 +255,6 @@
|
|||
projectRoot = "";
|
||||
targets = (
|
||||
DC6F1D362D94EADD0071B2B6 /* StikDebug */,
|
||||
F00DCAFE000000000000E001 /* StikDebugWidgets */,
|
||||
DC6F1D472D94EADF0071B2B6 /* StikDebugTests */,
|
||||
DC6F1D512D94EADF0071B2B6 /* StikDebugUITests */,
|
||||
);
|
||||
|
|
@ -352,13 +283,6 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F00DCAFE000000000000E005 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
|
@ -383,13 +307,6 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F00DCAFE000000000000E003 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
|
|
@ -403,11 +320,6 @@
|
|||
target = DC6F1D362D94EADD0071B2B6 /* StikDebug */;
|
||||
targetProxy = DC6F1D532D94EADF0071B2B6 /* PBXContainerItemProxy */;
|
||||
};
|
||||
F00DCAFE000000000000E00C /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = F00DCAFE000000000000E001 /* StikDebugWidgets */;
|
||||
targetProxy = F00DCAFE000000000000E00D /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
|
|
@ -756,64 +668,6 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
F00DCAFE000000000000E009 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = StikDebugWidgets/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = StikDebug;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.1.6;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.stik.stikdebug.widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F00DCAFE000000000000E00A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = StikDebugWidgets/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = StikDebug;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 3.1.6;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.stik.stikdebug.widgets;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
|
|
@ -853,15 +707,6 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F00DCAFE000000000000E008 /* Build configuration list for PBXNativeTarget "StikDebugWidgets" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F00DCAFE000000000000E009 /* Debug */,
|
||||
F00DCAFE000000000000E00A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@ enum AppBootstrapper {
|
|||
startConfiguredKeepAliveServices()
|
||||
applyDocumentPickerCopyWorkaround()
|
||||
NetworkPathMonitor.shared.start()
|
||||
// No hold is active at launch, so clear any Live Activity a previous
|
||||
// (possibly force-quit) run left showing in the Dynamic Island.
|
||||
KeepAliveLiveActivity.endStaleActivities()
|
||||
}
|
||||
|
||||
private static func registerDefaultSettings() {
|
||||
|
|
|
|||
|
|
@ -21,10 +21,6 @@
|
|||
<string>_stikdebug._tcp</string>
|
||||
<string>_stikdebug._udp</string>
|
||||
</array>
|
||||
<key>NSSupportsLiveActivities</key>
|
||||
<true/>
|
||||
<key>NSSupportsLiveActivitiesFrequentUpdates</key>
|
||||
<true/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
|
|
|
|||
|
|
@ -72,12 +72,7 @@ final class BackgroundAliveManager: ObservableObject {
|
|||
lock.unlock()
|
||||
|
||||
let name = displayName ?? bundleID
|
||||
DispatchQueue.main.async {
|
||||
self.activeAppName = name
|
||||
// Surface the hold in the Dynamic Island / Lock Screen so it stays
|
||||
// visible while the user is in the held app.
|
||||
KeepAliveLiveActivity.start(appName: name, bundleID: bundleID)
|
||||
}
|
||||
DispatchQueue.main.async { self.activeAppName = name }
|
||||
LogManager.shared.addInfoLog("Starting background keep-alive for \(name)")
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
|
|
@ -106,7 +101,6 @@ final class BackgroundAliveManager: ObservableObject {
|
|||
DispatchQueue.main.async {
|
||||
if stillCurrent {
|
||||
self.activeAppName = nil
|
||||
KeepAliveLiveActivity.end()
|
||||
}
|
||||
if !succeeded {
|
||||
showAlert(
|
||||
|
|
|
|||
|
|
@ -1,114 +0,0 @@
|
|||
//
|
||||
// KeepAliveLiveActivity.swift
|
||||
// StikDebug
|
||||
//
|
||||
// App-side controller for the background keep-alive Live Activity. Starts a
|
||||
// Live Activity when a hold begins so it shows in the Dynamic Island (on
|
||||
// compatible iPhones) and on the Lock Screen, and ends it when the hold stops.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if canImport(ActivityKit)
|
||||
import ActivityKit
|
||||
#endif
|
||||
|
||||
enum KeepAliveLiveActivity {
|
||||
private static let lock = NSLock()
|
||||
/// Type-erased storage for the current `Activity`, so this enum has no
|
||||
/// availability requirement of its own and callers don't need to guard.
|
||||
private static var storage: Any?
|
||||
|
||||
/// Start (or replace) the keep-alive Live Activity for the given app.
|
||||
static func start(appName: String, bundleID: String) {
|
||||
#if canImport(ActivityKit)
|
||||
guard #available(iOS 16.1, *) else { return }
|
||||
startActivity(appName: appName, bundleID: bundleID)
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Update the app name shown by the current Live Activity, if any.
|
||||
static func update(appName: String) {
|
||||
#if canImport(ActivityKit)
|
||||
guard #available(iOS 16.1, *) else { return }
|
||||
updateActivity(appName: appName)
|
||||
#endif
|
||||
}
|
||||
|
||||
/// End the current keep-alive Live Activity, if any.
|
||||
static func end() {
|
||||
#if canImport(ActivityKit)
|
||||
guard #available(iOS 16.1, *) else { return }
|
||||
endActivity()
|
||||
#endif
|
||||
}
|
||||
|
||||
/// End any keep-alive activities left running by a previous launch (for
|
||||
/// example if the app was force-quit or crashed mid-hold). Call this once at
|
||||
/// startup, when no hold is active.
|
||||
static func endStaleActivities() {
|
||||
#if canImport(ActivityKit)
|
||||
guard #available(iOS 16.1, *) else { return }
|
||||
for activity in Activity<KeepAliveActivityAttributes>.activities {
|
||||
Task { await activity.end(nil, dismissalPolicy: .immediate) }
|
||||
}
|
||||
lock.lock()
|
||||
storage = nil
|
||||
lock.unlock()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if canImport(ActivityKit)
|
||||
@available(iOS 16.1, *)
|
||||
private static func startActivity(appName: String, bundleID: String) {
|
||||
guard ActivityAuthorizationInfo().areActivitiesEnabled else {
|
||||
LogManager.shared.addInfoLog("Keep-alive Live Activity not started: Live Activities are disabled in Settings")
|
||||
return
|
||||
}
|
||||
|
||||
// Only one hold runs at a time, so make sure any stale activity is gone.
|
||||
endActivity()
|
||||
|
||||
let attributes = KeepAliveActivityAttributes(appName: appName, bundleID: bundleID)
|
||||
let state = KeepAliveActivityAttributes.ContentState(appName: appName)
|
||||
|
||||
do {
|
||||
let activity = try Activity.request(
|
||||
attributes: attributes,
|
||||
content: ActivityContent(state: state, staleDate: nil)
|
||||
)
|
||||
lock.lock()
|
||||
storage = activity
|
||||
lock.unlock()
|
||||
} catch {
|
||||
LogManager.shared.addErrorLog("Keep-alive Live Activity failed to start: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 16.1, *)
|
||||
private static func updateActivity(appName: String) {
|
||||
lock.lock()
|
||||
let activity = storage as? Activity<KeepAliveActivityAttributes>
|
||||
lock.unlock()
|
||||
guard let activity else { return }
|
||||
|
||||
let state = KeepAliveActivityAttributes.ContentState(appName: appName)
|
||||
Task {
|
||||
await activity.update(ActivityContent(state: state, staleDate: nil))
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 16.1, *)
|
||||
private static func endActivity() {
|
||||
lock.lock()
|
||||
let activity = storage as? Activity<KeepAliveActivityAttributes>
|
||||
storage = nil
|
||||
lock.unlock()
|
||||
guard let activity else { return }
|
||||
|
||||
Task {
|
||||
await activity.end(nil, dismissalPolicy: .immediate)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
//
|
||||
// KeepAliveActivityAttributes.swift
|
||||
// StikDebug
|
||||
//
|
||||
// Shared between the app (which starts/updates/ends the activity) and the
|
||||
// widget extension (which renders it in the Dynamic Island / on the Lock
|
||||
// Screen). Keep this file in the StikDebugShared group so both targets compile
|
||||
// the same type.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if canImport(ActivityKit)
|
||||
import ActivityKit
|
||||
|
||||
@available(iOS 16.1, *)
|
||||
struct KeepAliveActivityAttributes: ActivityAttributes {
|
||||
/// The parts of the activity that change while it is live.
|
||||
struct ContentState: Codable, Hashable {
|
||||
/// The display name of the app currently being held alive.
|
||||
var appName: String
|
||||
}
|
||||
|
||||
/// The app being held alive when the activity started.
|
||||
var appName: String
|
||||
/// The bundle identifier of that app.
|
||||
var bundleID: String
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.widgetkit-extension</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
//
|
||||
// KeepAliveLiveActivityWidget.swift
|
||||
// StikDebugWidgets
|
||||
//
|
||||
// Live Activity presentation for the background keep-alive session. Shows the
|
||||
// held app in the Dynamic Island (compact, expanded, and minimal) and on the
|
||||
// Lock Screen.
|
||||
//
|
||||
|
||||
import WidgetKit
|
||||
import SwiftUI
|
||||
import ActivityKit
|
||||
|
||||
@available(iOS 16.1, *)
|
||||
struct KeepAliveLiveActivityWidget: Widget {
|
||||
var body: some WidgetConfiguration {
|
||||
ActivityConfiguration(for: KeepAliveActivityAttributes.self) { context in
|
||||
// Lock Screen / banner presentation.
|
||||
KeepAliveLockScreenView(appName: context.state.appName)
|
||||
.activityBackgroundTint(Color.black.opacity(0.55))
|
||||
.activitySystemActionForegroundColor(.green)
|
||||
} dynamicIsland: { context in
|
||||
DynamicIsland {
|
||||
DynamicIslandExpandedRegion(.leading) {
|
||||
Image(systemName: "bolt.circle.fill")
|
||||
.font(.title2)
|
||||
.foregroundStyle(.green)
|
||||
.padding(.leading, 4)
|
||||
}
|
||||
DynamicIslandExpandedRegion(.trailing) {
|
||||
Text("JIT")
|
||||
.font(.caption.weight(.bold))
|
||||
.foregroundStyle(.green)
|
||||
.padding(.trailing, 4)
|
||||
}
|
||||
DynamicIslandExpandedRegion(.center) {
|
||||
Text(context.state.appName)
|
||||
.font(.headline)
|
||||
.lineLimit(1)
|
||||
.minimumScaleFactor(0.7)
|
||||
}
|
||||
DynamicIslandExpandedRegion(.bottom) {
|
||||
Text("Held alive in the background")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
} compactLeading: {
|
||||
Image(systemName: "bolt.circle.fill")
|
||||
.foregroundStyle(.green)
|
||||
} compactTrailing: {
|
||||
Text(context.state.appName)
|
||||
.font(.caption2)
|
||||
.lineLimit(1)
|
||||
.frame(maxWidth: 64)
|
||||
} minimal: {
|
||||
Image(systemName: "bolt.circle.fill")
|
||||
.foregroundStyle(.green)
|
||||
}
|
||||
.keylineTint(.green)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 16.1, *)
|
||||
private struct KeepAliveLockScreenView: View {
|
||||
let appName: String
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 12) {
|
||||
Image(systemName: "bolt.circle.fill")
|
||||
.font(.title)
|
||||
.foregroundStyle(.green)
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("Keeping \(appName) alive")
|
||||
.font(.headline)
|
||||
.lineLimit(1)
|
||||
.minimumScaleFactor(0.7)
|
||||
Text("Held in the background")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
//
|
||||
// StikDebugWidgetsBundle.swift
|
||||
// StikDebugWidgets
|
||||
//
|
||||
// Widget extension bundle. Hosts the keep-alive Live Activity so it can be
|
||||
// rendered in the Dynamic Island and on the Lock Screen.
|
||||
//
|
||||
|
||||
import WidgetKit
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct StikDebugWidgetsBundle: WidgetBundle {
|
||||
var body: some Widget {
|
||||
KeepAliveLiveActivityWidget()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue