Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent retriggering of event actions #47

Merged
merged 27 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
256f80b
add skip functionalities
robertherber Feb 14, 2025
efddc3d
sync before and after each event
robertherber Feb 14, 2025
9b56595
Fix so renamed INTERNALLY_TEST_EXAMPLE_PROJECT doesnt cause console e…
robertherber Feb 14, 2025
1db62f7
improve test coverage
robertherber Feb 14, 2025
da8295e
improve test coverage, cleaning up
robertherber Feb 15, 2025
49c60ec
add reloadDeviceActivityCenter to index
robertherber Feb 15, 2025
47104e9
introduce COPY_TO_TARGET_FOLDER
robertherber Feb 15, 2025
952c616
publish 0.4.0
robertherber Feb 15, 2025
3019546
Add skipIfLargerEventRecordedSinceMonitoringStarted
robertherber Feb 15, 2025
653b926
rename to skipIfLargerEventRecordedSinceIntervalStarted
robertherber Feb 15, 2025
0e75445
bump version
robertherber Feb 15, 2025
734dc52
change activitynames
robertherber Feb 15, 2025
c1efe8b
reinit onDeviceActivityDetected listener on deviceactivitycenter reload
robertherber Feb 17, 2025
635b5cb
bump version
robertherber Feb 17, 2025
a0d7ea5
add neverTriggerBefore action param
robertherber Feb 17, 2025
5256a63
bump version
robertherber Feb 17, 2025
0f50efe
Clean up blockSelectedApps
robertherber Feb 17, 2025
7fbb3b4
add shield config triggeredBy for traceability
robertherber Feb 17, 2025
318a1b3
fix unblockedselection
robertherber Feb 17, 2025
a00f582
Add triggeredBy to block actions
robertherber Feb 17, 2025
50465e9
bump version
robertherber Feb 17, 2025
87ad04e
add updatedAt to shieldConfiguration/shieldActions
robertherber Feb 17, 2025
7e7a65d
bump version
robertherber Feb 17, 2025
d3a11c2
Expose triggeredBy the whole way
robertherber Feb 17, 2025
acdb4aa
bump version
robertherber Feb 17, 2025
137ce51
Fix build issue and bump version
robertherber Feb 17, 2025
675e8a7
rename to removePrefixIfPresent
robertherber Feb 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ disabled_rules:
- type_body_length
- cyclomatic_complexity
- file_length
- function_parameter_count

included:
- ios
Expand Down
43 changes: 43 additions & 0 deletions example/ios/Tests/SharedTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,46 @@ class SharedTests: XCTestCase {
XCTAssertEqual(result["score"] as? String, "{asNumber:missingValue}")
}
}

class SharedTests2: XCTestCase {
func isHigherEventNumTest() {
let isLower = isHigherEvent(eventName: "5", higherThan: "10")
let isEqual = isHigherEvent(eventName: "10", higherThan: "10")
let isHigher = isHigherEvent(eventName: "15", higherThan: "10")

XCTAssertTrue(isHigher)
XCTAssertFalse(isEqual)
XCTAssertFalse(isLower)
}

func isHigherEventStringTest() {
let isHigherBecauseString = isHigherEvent(eventName: "prefix_5", higherThan: "prefix_10")
let isEqual = isHigherEvent(eventName: "prefix_10", higherThan: "prefix_10")
let isHigher = isHigherEvent(eventName: "prefix_15", higherThan: "prefix_10")

XCTAssertTrue(isHigher)
XCTAssertFalse(isEqual)
XCTAssertFalse(isHigherBecauseString)
}

func replaceTest() {
let five = replace(
key: "event_with_prefix_5",
prefix: "event_with_prefix_"
)

let empty = replace(
key: "event_with_prefix_",
prefix: "event_with_prefix_"
)

let nonmatching = replace(
key: "dfgsfgsdfgsdfg",
prefix: "event_with_prefix_"
)

XCTAssertEqual(five, "5")
XCTAssertEqual(empty, "")
XCTAssertEqual(nonmatching, "dfgsfgsdfgsdfg")
}
}
84 changes: 82 additions & 2 deletions ios/Shared.swift
Original file line number Diff line number Diff line change
Expand Up @@ -541,13 +541,93 @@ func getColor(color: [String: Double]?) -> UIColor? {
return nil
}

func persistToUserDefaults(activityName: String, callbackName: String, eventName: String? = nil) {
let now = (Date().timeIntervalSince1970 * 1000).rounded()
func userDefaultKeyForEvent(activityName: String, callbackName: String, eventName: String? = nil)
-> String {

let fullEventName =
eventName == nil
? "events_\(activityName)_\(callbackName)"
: "events_\(activityName)_\(callbackName)_\(eventName!)"

return fullEventName
}

func persistToUserDefaults(activityName: String, callbackName: String, eventName: String? = nil) {
let now = (Date().timeIntervalSince1970 * 1000).rounded()

let fullEventName = userDefaultKeyForEvent(
activityName: activityName,
callbackName: callbackName,
eventName: eventName
)

userDefaults?.set(now, forKey: fullEventName)

CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication)
}

func isHigherEvent(eventName: String, higherThan: String) -> Bool {
if let eventNameNum = Double(eventName), let higherThanNum = Double(higherThan) {
return eventNameNum > higherThanNum
} else {
return eventName > higherThan
}
}

func replace(key: String, prefix: String) -> String {
if key.hasPrefix(prefix) {
return String(key.dropFirst(prefix.count))
}

return key
}

func hasHigherTriggeredEvent(
activityName: String,
callbackName: String,
eventName: String?,
afterDate: Double
) -> Bool {
let prefix = "events_\(activityName)_"

if let actualDict = userDefaults?.dictionaryRepresentation() {
let higherEvent = actualDict.first(where: { (key: String, value: Any) in
if let triggeredAt = value as? Double {
return
key
.starts(
with: prefix
)
&& triggeredAt > afterDate
&& (eventName != nil
? isHigherEvent(
eventName: replace(key: key, prefix: prefix),
higherThan: eventName!
) : true)
}
return false

})

if higherEvent != nil {
return true
}
}

return false
}

func getLastTriggeredTimeFromUserDefaults(
activityName: String, callbackName: String, eventName: String? = nil
) -> Double? {

let fullEventName = userDefaultKeyForEvent(
activityName: activityName,
callbackName: callbackName,
eventName: eventName
)

return userDefaults?.double(forKey: fullEventName)
}

func traverseDirectory(at path: String) {
Expand Down
28 changes: 28 additions & 0 deletions src/ReactNativeDeviceActivity.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,33 +176,57 @@ export type Action =
shieldId?: string;
sleepBefore?: number;
sleepAfter?: number;
skipIfAlreadyTriggeredAfter?: Date;
skipIfLargerEventRecordedAfter?: Date;
skipIfAlreadyTriggeredWithinMS?: number;
skipIfLargerEventRecordedWithinMS?: number;
}
| {
type: "unblockAllApps";
sleepBefore?: number;
sleepAfter?: number;
skipIfAlreadyTriggeredAfter?: Date;
skipIfLargerEventRecordedAfter?: Date;
skipIfAlreadyTriggeredWithinMS?: number;
skipIfLargerEventRecordedWithinMS?: number;
}
| {
type: "resetUnblockedSelection";
sleepBefore?: number;
sleepAfter?: number;
skipIfAlreadyTriggeredAfter?: Date;
skipIfLargerEventRecordedAfter?: Date;
skipIfAlreadyTriggeredWithinMS?: number;
skipIfLargerEventRecordedWithinMS?: number;
}
| {
type: "blockAllApps";
shieldId?: string;
sleepBefore?: number;
sleepAfter?: number;
skipIfAlreadyTriggeredAfter?: Date;
skipIfLargerEventRecordedAfter?: Date;
skipIfAlreadyTriggeredWithinMS?: number;
skipIfLargerEventRecordedWithinMS?: number;
}
| {
type: "sendNotification";
payload: NotificationPayload;
sleepBefore?: number;
sleepAfter?: number;
skipIfAlreadyTriggeredAfter?: Date;
skipIfLargerEventRecordedAfter?: Date;
skipIfAlreadyTriggeredWithinMS?: number;
skipIfLargerEventRecordedWithinMS?: number;
}
| {
type: "openApp";
sleepBefore?: number;
sleepAfter?: number;
skipIfAlreadyTriggeredAfter?: Date;
skipIfLargerEventRecordedAfter?: Date;
skipIfAlreadyTriggeredWithinMS?: number;
skipIfLargerEventRecordedWithinMS?: number;
}
| {
type: "sendHttpRequest";
Expand All @@ -214,6 +238,10 @@ export type Action =
};
sleepBefore?: number;
sleepAfter?: number;
skipIfAlreadyTriggeredAfter?: Date;
skipIfLargerEventRecordedAfter?: Date;
skipIfAlreadyTriggeredWithinMS?: number;
skipIfLargerEventRecordedWithinMS?: number;
};

export type DeviceActivityEventRaw = Omit<
Expand Down
13 changes: 12 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,18 @@ export const configureActions = ({
? `actions_for_${activityName}_${callbackName}_${eventName}`
: `actions_for_${activityName}_${callbackName}`;

userDefaultsSet(key, actions);
userDefaultsSet(
key,
actions.map((action) => ({
...action,
skipIfLargerEventRecordedAfter: action.skipIfLargerEventRecordedAfter
? action.skipIfLargerEventRecordedAfter.getTime()
: undefined,
skipIfAlreadyTriggeredAfter: action.skipIfAlreadyTriggeredAfter
? action.skipIfAlreadyTriggeredAfter.getTime()
: undefined,
})),
);
};

export const cleanUpAfterActivity = (activityName: string) => {
Expand Down
Loading
Loading