Skip to content

Commit

Permalink
refactor appintent payload
Browse files Browse the repository at this point in the history
  • Loading branch information
lukesthl committed Jan 15, 2024
1 parent 17446f2 commit 2290325
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 66 deletions.
1 change: 0 additions & 1 deletion apps/expo/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import "../data/logger";

import { ThemeProvider, useTheme } from "../components/theme-provider";
import { clearShortcutListener, listenForShortcut } from "../data/shortcut.listener";
import { ShortCutPayload } from "../data/shortcut.payload";
import config from "../tamagui.config";

export { ErrorBoundary } from "expo-router";
Expand Down
4 changes: 2 additions & 2 deletions apps/expo/data/shortcut.listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ export const listenForShortcut = async (): Promise<{ app: string; timestamp: num
if (appPayload && appPayload.event === "break-start") {
clearInterval(intervalId ?? 0);
console.log(`took ${new Date().getTime() - time}ms`);
console.log(`openedApp: ${appPayload.app}`);
console.log(`openedApp: ${appPayload.openedApp}`);

resolve({ app: appPayload.app, timestamp: parseInt(appPayload.timestamp, 10) });
resolve({ app: appPayload.openedApp, timestamp: appPayload.timestamp });
} else {
throw new Error("no app");
}
Expand Down
28 changes: 18 additions & 10 deletions apps/expo/data/shortcut.payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,47 @@ import * as FileSystem from "expo-file-system";

import { appConfig } from "../constants/app.config";

interface IPayload {
openedApp: string;
timestamp: number;
event: "break-start" | "app-reopen" | "break-skip";
}

class ShortCutPayloadSingleton {
private readonly storageKey = "openedApp";
private pathSplitted = FileSystem.documentDirectory?.split("/");
private appPath = this.pathSplitted?.slice(0, this.pathSplitted.length - 2).join("/");
private dataPath = `${this.appPath}/Library/Application Support/${appConfig.bundleIdentifier}/RCTAsyncLocalStorage_V1/appintent.json`;

private loadAppIntentPayload = async (): Promise<Record<string, unknown>> => {
private loadAppIntentPayload = async (): Promise<IPayload | undefined> => {
const string = await FileSystem.readAsStringAsync(this.dataPath);
const payload = JSON.parse(string) as Record<string, unknown>;
const payload = JSON.parse(string) as IPayload;
return payload;
};

public getPayload = async (): Promise<{ app: string; timestamp: string; event: string } | null> => {
public getPayload = async (): Promise<IPayload | null> => {
const payload = await this.loadAppIntentPayload();
const openedAppPayload = payload[this.storageKey] as string | undefined;
if (openedAppPayload) {
const [openedApp, timestamp, event] = openedAppPayload.split("_") as [string, string, string];
return { app: openedApp, timestamp, event };
if (payload) {
return payload;
} else {
return null;
}
};

public update = async (app: string, event: string) => {
const appIntentPayload = await this.loadAppIntentPayload();
if (!appIntentPayload) {
return;
}
appIntentPayload.openedApp = `${app}_${Date.now()}_${event}`;
await FileSystem.writeAsStringAsync(this.dataPath, JSON.stringify(appIntentPayload));
};

public clear = async () => {
const appIntentPayload = await this.loadAppIntentPayload();
delete appIntentPayload.openedApp;
await FileSystem.writeAsStringAsync(this.dataPath, JSON.stringify(appIntentPayload));
if (!appIntentPayload) {
return;
}
await FileSystem.writeAsStringAsync(this.dataPath, JSON.stringify({}));
};
}

Expand Down
102 changes: 49 additions & 53 deletions apps/expo/targets/intents/DigitalBreak.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,15 @@ struct Manifest: Decodable {
}

struct AppIntentPayload: Codable {
var openedApp: String?
var openedApp: String
var timestamp: Double
var event: Event
}

enum Event: String, Codable {
case breakStart = "break-start"
case appReopen = "app-reopen"
case breakSkip = "break-skip"
}

typealias AppInfoList = [String: AppInfo]
Expand Down Expand Up @@ -156,66 +164,54 @@ struct DigitalBreak: AppIntent {
func perform() async throws -> some IntentResult & ReturnsValue<Bool> {
var appIntentPayload = getAppIntentPayload()
var appInfo = fetchAppItem(with: appPrompt!)
var canOpenApp = true

var isActive = true
var outOfTimeRange = false
do {
if appIntentPayload?.openedApp != nil && appInfo != nil {
canOpenApp = appInfo!.active
if canOpenApp,
let payload = appIntentPayload,
let openedApp = payload.openedApp,
!openedApp.contains("_app-reopen")
{
let lastOpen = appIntentPayload?.openedApp?.split(separator: "_")
let lastOpenTime = Double(lastOpen![1])!
let quickAppSwitchDurationAsTimestamp =
Double(appInfo!.settings.quickAppSwitchDurationMinutes * 60)
let timeSinceLastOpen = Date().timeIntervalSince1970 - lastOpenTime
let timeSinceLastOpenMinutes = timeSinceLastOpen / 60
print("timeSinceLastOpen", timeSinceLastOpenMinutes)
canOpenApp =
Double(appInfo?.settings.quickAppSwitchDurationMinutes ?? 0)
< Double(
timeSinceLastOpenMinutes)
}
if appInfo != nil {
isActive = appInfo!.active

let lastOpen = appIntentPayload!.timestamp
let quickAppSwitchDurationAsTimestamp =
Double(appInfo!.settings.quickAppSwitchDurationMinutes * 60)
let timeSinceLastOpen = Date().timeIntervalSince1970 - lastOpen
let timeSinceLastOpenMinutes = timeSinceLastOpen / 60
print("timeSinceLastOpen", timeSinceLastOpenMinutes)
outOfTimeRange =
Double(appInfo?.settings.quickAppSwitchDurationMinutes ?? 0)
<= Double(
timeSinceLastOpenMinutes)
}
} catch {
print("Error while fetching apps: \(error)")
}
if canOpenApp {
if let payload = appIntentPayload,
let openedApp = payload.openedApp,
openedApp.contains("_app-reopen")
{
appIntentPayload?.openedApp = nil
print("dont open app because it was just reopened")
} else {
let app = appPrompt
appIntentPayload = AppIntentPayload(
openedApp: "\(app!)_\(Date().timeIntervalSince1970)_break-start")
print("open app")
}
if appIntentPayload != nil {
let (storageDirectory, storageFile) = getStorageDirAndFile(fileName: "appintent.json")
let fileManager = FileManager.default
do {
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(appIntentPayload)
if !fileManager.fileExists(atPath: storageDirectory.path) {
try fileManager.createDirectory(
atPath: storageDirectory.path, withIntermediateDirectories: true, attributes: nil)
}
let stringified = String(data: jsonData, encoding: .utf8)!
try stringified.write(to: storageFile, atomically: true, encoding: .utf8)
} catch {
print(error)
}
if appIntentPayload != nil && isActive && appIntentPayload?.event == Event.breakStart {
return .result(
value: true)
}else if (appIntentPayload == nil) {
appIntentPayload = AppIntentPayload(
openedApp: appPrompt!, timestamp: Date().timeIntervalSince1970, event: Event.breakStart)
}else {
appIntentPayload?.event = Event.breakSkip
}
let (storageDirectory, storageFile) = getStorageDirAndFile(fileName: "appintent.json")
let fileManager = FileManager.default
do {
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(appIntentPayload)
if !fileManager.fileExists(atPath: storageDirectory.path) {
try fileManager.createDirectory(
atPath: storageDirectory.path, withIntermediateDirectories: true, attributes: nil)
}
} else {
print("dont open app because settings disallow it")
let stringified = String(data: jsonData, encoding: .utf8)!
try stringified.write(to: storageFile, atomically: true, encoding: .utf8)
} catch {
print(error)
}

return .result(
value: canOpenApp && appIntentPayload?.openedApp != nil)
value: appIntentPayload?.event != Event.breakSkip
)
}
func asString(dict: [String: String]) -> String {
do {
Expand Down

0 comments on commit 2290325

Please sign in to comment.