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

Periodically check if we have inflight payments #635

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
"@capacitor/clipboard": "^5.0.6",
"@capacitor/core": "^5.2.2",
"@capacitor/filesystem": "^5.1.4",
"@capacitor/share": "^5.0.6",
"@capacitor/haptics": "^5.0.6",
"@capacitor/share": "^5.0.6",
"@capacitor/toast": "^5.0.6",
"@kobalte/core": "^0.9.8",
"@kobalte/tailwindcss": "^0.5.0",
Expand Down
74 changes: 74 additions & 0 deletions public/sw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
self.addEventListener("periodicsync", (event) => {
if (event.tag === "check-inflight-payments") {
event.waitUntil(checkPaymentsInFlight());
}
});

async function checkPaymentsInFlight() {
console.log('checkPaymentsInFlight');
const db = await openDatabase();

const transaction = db.transaction('wallet_store', 'readonly');
const store = transaction.objectStore('wallet_store');

// Get keys prefixed with "payment_outbound"
const keys = await getAllKeysWithPrefix(store, 'payment_outbound');

for (let key of keys) {
const payment = await get(store, key);
console.log(payment.status);
if (payment && payment.status === "InFlight") {
showNotification();
break;
}
}
transaction.commit();
}

function openDatabase(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const request = indexedDB.open('wallet');
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}

function getAllKeysWithPrefix(store: IDBObjectStore, prefix: string): Promise<string[]> {
return new Promise((resolve, reject) => {
const keys: string[] = [];
const cursorRequest = store.openKeyCursor();

cursorRequest.onsuccess = function(event) {
const cursor = (event.target as IDBRequest).result as IDBCursor;
if (cursor) {
if (cursor.key.toString().startsWith(prefix)) {
keys.push(cursor.key.toString());
}
cursor.continue();
} else {
resolve(keys);
}
};

cursorRequest.onerror = function() {
reject(cursorRequest.error);
};
});
}

function get(store: IDBObjectStore, key: string): Promise<any> {
return new Promise((resolve, reject) => {
const request = store.get(key);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
}

function showNotification() {
// todo make pretty
self.registration.showNotification('Payment Alert', {
body: 'There are payments with status InFlight.',
// icon: '/path/to/icon.png', // You can specify an icon if you have one
// badge: '/path/to/badge.png' // You can specify a badge if you have one
});
}
27 changes: 27 additions & 0 deletions src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,37 @@
import { FeedbackLink } from "~/routes/Feedback";
import { useMegaStore } from "~/state/megaStore";

async function registerPeriodicInFlightCheck() {
const registration = await navigator.serviceWorker.ready;
try {
// Request notification permission from the user
Notification.requestPermission().then(async (permission) => {
if (permission === "granted") {
console.log("Notification permission granted.");

await registration.periodicSync.register(

Check failure on line 35 in src/routes/index.tsx

View workflow job for this annotation

GitHub Actions / code_quality

Property 'periodicSync' does not exist on type 'ServiceWorkerRegistration'.
"check-inflight-payments",
{
minInterval: 60 * 60 * 1000 // every hour
}
);
} else {
console.error("Notification permission denied.");
}
});
} catch (e) {
console.warn("Periodic Sync could not be registered!");
console.error(e);
}
}

export default function App() {
const i18n = useI18n();
const [state, _actions] = useMegaStore();

// run registerPeriodicInFlightCheck in background
const _ = registerPeriodicInFlightCheck();

return (
<SafeArea>
<DefaultMain>
Expand Down
6 changes: 5 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ const commitHash = process.env.VITE_COMMIT_HASH ?? child.execSync("git rev-parse

const pwaOptions: Partial<VitePWAOptions> = {
base: "/",
injectRegister: 'inline',
filename: 'sw.ts',
strategies: 'injectManifest',
registerType: "autoUpdate",
devOptions: {
enabled: false
enabled: true,
type: "module"
},
includeAssets: ["favicon.ico", "robots.txt"],
manifest: manifest
Expand Down
Loading