mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-04-23 19:37:52 +00:00
change encoding of saved local data
This commit is contained in:
parent
b52abbc007
commit
530aa0cacc
@ -115,29 +115,36 @@ const requestQueueAnnouncements = new RequestQueueWithPromise(1);
|
|||||||
let isMobile = true;
|
let isMobile = true;
|
||||||
|
|
||||||
function handleNotificationClick(notificationId) {
|
function handleNotificationClick(notificationId) {
|
||||||
// Determine the type of notification by parsing notificationId
|
// Decode the notificationId if it was encoded
|
||||||
const isDirect = notificationId.includes("_type=direct_");
|
const decodedNotificationId = decodeURIComponent(notificationId);
|
||||||
const isGroup = notificationId.includes("_type=group_");
|
|
||||||
const isGroupAnnouncement = notificationId.includes(
|
// Determine the type of notification by parsing decodedNotificationId
|
||||||
"_type=group-announcement_"
|
const isDirect = decodedNotificationId.includes("_type=direct_");
|
||||||
);
|
const isGroup = decodedNotificationId.includes("_type=group_");
|
||||||
const isNewThreadPost = notificationId.includes("_type=thread-post_");
|
const isGroupAnnouncement = decodedNotificationId.includes("_type=group-announcement_");
|
||||||
|
const isNewThreadPost = decodedNotificationId.includes("_type=thread-post_");
|
||||||
|
|
||||||
|
// Helper function to extract parameter values safely
|
||||||
|
function getParameterValue(id, key) {
|
||||||
|
const match = id.match(new RegExp(`${key}=([^_]+)`));
|
||||||
|
return match ? match[1] : null;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle specific notification types and post the message accordingly
|
// Handle specific notification types and post the message accordingly
|
||||||
if (isDirect) {
|
if (isDirect) {
|
||||||
const fromValue = notificationId.split("_from=")[1];
|
const fromValue = getParameterValue(decodedNotificationId, "_from");
|
||||||
window.postMessage(
|
window.postMessage(
|
||||||
{ action: "NOTIFICATION_OPEN_DIRECT", payload: { from: fromValue } },
|
{ action: "NOTIFICATION_OPEN_DIRECT", payload: { from: fromValue } },
|
||||||
"*"
|
"*"
|
||||||
);
|
);
|
||||||
} else if (isGroup) {
|
} else if (isGroup) {
|
||||||
const fromValue = notificationId.split("_from=")[1];
|
const fromValue = getParameterValue(decodedNotificationId, "_from");
|
||||||
window.postMessage(
|
window.postMessage(
|
||||||
{ action: "NOTIFICATION_OPEN_GROUP", payload: { from: fromValue } },
|
{ action: "NOTIFICATION_OPEN_GROUP", payload: { from: fromValue } },
|
||||||
"*"
|
"*"
|
||||||
);
|
);
|
||||||
} else if (isGroupAnnouncement) {
|
} else if (isGroupAnnouncement) {
|
||||||
const fromValue = notificationId.split("_from=")[1];
|
const fromValue = getParameterValue(decodedNotificationId, "_from");
|
||||||
window.postMessage(
|
window.postMessage(
|
||||||
{
|
{
|
||||||
action: "NOTIFICATION_OPEN_ANNOUNCEMENT_GROUP",
|
action: "NOTIFICATION_OPEN_ANNOUNCEMENT_GROUP",
|
||||||
@ -146,18 +153,23 @@ function handleNotificationClick(notificationId) {
|
|||||||
"*"
|
"*"
|
||||||
);
|
);
|
||||||
} else if (isNewThreadPost) {
|
} else if (isNewThreadPost) {
|
||||||
const dataValue = notificationId.split("_data=")[1];
|
const dataValue = getParameterValue(decodedNotificationId, "_data");
|
||||||
const dataParsed = JSON.parse(dataValue);
|
try {
|
||||||
window.postMessage(
|
const dataParsed = JSON.parse(dataValue);
|
||||||
{
|
window.postMessage(
|
||||||
action: "NOTIFICATION_OPEN_THREAD_NEW_POST",
|
{
|
||||||
payload: { data: dataParsed },
|
action: "NOTIFICATION_OPEN_THREAD_NEW_POST",
|
||||||
},
|
payload: { data: dataParsed },
|
||||||
"*"
|
},
|
||||||
);
|
"*"
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error parsing JSON data for thread post notification:", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const isMobileDevice = () => {
|
const isMobileDevice = () => {
|
||||||
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
||||||
|
|
||||||
@ -400,8 +412,8 @@ const handleNotificationDirect = async (directs) => {
|
|||||||
|
|
||||||
if (newActiveChats?.length === 0) return;
|
if (newActiveChats?.length === 0) return;
|
||||||
|
|
||||||
let newestLatestTimestamp;
|
let newestLatestTimestamp = null;
|
||||||
let oldestLatestTimestamp;
|
let oldestLatestTimestamp = null;
|
||||||
// Find the latest timestamp from newActiveChats
|
// Find the latest timestamp from newActiveChats
|
||||||
newActiveChats?.forEach((newChat) => {
|
newActiveChats?.forEach((newChat) => {
|
||||||
if (
|
if (
|
||||||
@ -434,10 +446,10 @@ const handleNotificationDirect = async (directs) => {
|
|||||||
}`;
|
}`;
|
||||||
const body = "You have received a new direct message";
|
const body = "You have received a new direct message";
|
||||||
const notificationId =
|
const notificationId =
|
||||||
"chat_notification_" +
|
encodeURIComponent("chat_notification_" +
|
||||||
Date.now() +
|
Date.now() +
|
||||||
"_type=direct" +
|
"_type=direct" +
|
||||||
`_from=${newestLatestTimestamp.address}`;
|
`_from=${newestLatestTimestamp.address}`);
|
||||||
const notification = new window.Notification(title, {
|
const notification = new window.Notification(title, {
|
||||||
body,
|
body,
|
||||||
data: { id: notificationId },
|
data: { id: notificationId },
|
||||||
@ -451,7 +463,7 @@ const handleNotificationDirect = async (directs) => {
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.close();
|
notification.close();
|
||||||
}, 5000);
|
}, 10000);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isFocused) {
|
if (!isFocused) {
|
||||||
@ -471,10 +483,10 @@ const handleNotificationDirect = async (directs) => {
|
|||||||
|
|
||||||
// Create a unique notification ID with type and sender information
|
// Create a unique notification ID with type and sender information
|
||||||
const notificationId =
|
const notificationId =
|
||||||
"chat_notification_" +
|
encodeURIComponent("chat_notification_" +
|
||||||
Date.now() +
|
Date.now() +
|
||||||
"_type=direct" +
|
"_type=direct" +
|
||||||
`_from=${newestLatestTimestamp.address}`;
|
`_from=${newestLatestTimestamp.address}`);
|
||||||
|
|
||||||
const title = "New Direct message!";
|
const title = "New Direct message!";
|
||||||
const body = "You have received a new direct message";
|
const body = "You have received a new direct message";
|
||||||
@ -493,7 +505,7 @@ const handleNotificationDirect = async (directs) => {
|
|||||||
// Automatically close the notification after 5 seconds if not clicked
|
// Automatically close the notification after 5 seconds if not clicked
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.close();
|
notification.close();
|
||||||
}, 5000); // Close after 5 seconds
|
}, 10000); // Close after 5 seconds
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setChatHeadsDirect(dataDirects);
|
setChatHeadsDirect(dataDirects);
|
||||||
@ -619,8 +631,8 @@ const handleNotification = async (groups) => {
|
|||||||
const oldActiveChats = await getChatHeads();
|
const oldActiveChats = await getChatHeads();
|
||||||
|
|
||||||
let results = [];
|
let results = [];
|
||||||
let newestLatestTimestamp;
|
let newestLatestTimestamp = null;
|
||||||
let oldestLatestTimestamp;
|
let oldestLatestTimestamp = null;
|
||||||
// Find the latest timestamp from newActiveChats
|
// Find the latest timestamp from newActiveChats
|
||||||
newActiveChats?.forEach((newChat) => {
|
newActiveChats?.forEach((newChat) => {
|
||||||
if (
|
if (
|
||||||
@ -659,10 +671,10 @@ const handleNotification = async (groups) => {
|
|||||||
|
|
||||||
// Create a unique notification ID with type and group information
|
// Create a unique notification ID with type and group information
|
||||||
const notificationId =
|
const notificationId =
|
||||||
"chat_notification_" +
|
encodeURIComponent("chat_notification_" +
|
||||||
Date.now() +
|
Date.now() +
|
||||||
"_type=group" +
|
"_type=group" +
|
||||||
`_from=${newestLatestTimestamp.groupId}`;
|
`_from=${newestLatestTimestamp.groupId}`);
|
||||||
|
|
||||||
const title = "New Group Message!";
|
const title = "New Group Message!";
|
||||||
const body = `You have received a new message from ${newestLatestTimestamp?.groupName}`;
|
const body = `You have received a new message from ${newestLatestTimestamp?.groupName}`;
|
||||||
@ -681,7 +693,7 @@ const handleNotification = async (groups) => {
|
|||||||
// Automatically close the notification after 5 seconds if not clicked
|
// Automatically close the notification after 5 seconds if not clicked
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.close();
|
notification.close();
|
||||||
}, 5000); // Close after 5 seconds
|
}, 10000); // Close after 5 seconds
|
||||||
|
|
||||||
lastGroupNotification = Date.now();
|
lastGroupNotification = Date.now();
|
||||||
}
|
}
|
||||||
@ -703,7 +715,7 @@ const handleNotification = async (groups) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Generate a unique notification ID
|
// Generate a unique notification ID
|
||||||
const notificationId = "chat_notification_" + Date.now();
|
const notificationId = encodeURIComponent("chat_notification_" + Date.now());
|
||||||
|
|
||||||
const title = "New Group Message!";
|
const title = "New Group Message!";
|
||||||
const body = "You have received a new message from one of your groups";
|
const body = "You have received a new message from one of your groups";
|
||||||
@ -723,7 +735,7 @@ const handleNotification = async (groups) => {
|
|||||||
// Automatically close the notification after 5 seconds if it’s not clicked
|
// Automatically close the notification after 5 seconds if it’s not clicked
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.close();
|
notification.close();
|
||||||
}, 5000); // Close after 5 seconds
|
}, 10000); // Close after 5 seconds
|
||||||
|
|
||||||
lastGroupNotification = Date.now();
|
lastGroupNotification = Date.now();
|
||||||
}
|
}
|
||||||
@ -1332,7 +1344,6 @@ export async function handleActiveGroupDataFromSocket({ groups, directs }) {
|
|||||||
groups: groups || [], // Your groups data here
|
groups: groups || [], // Your groups data here
|
||||||
directs: directs || [], // Your directs data here
|
directs: directs || [], // Your directs data here
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save the active data to localStorage
|
// Save the active data to localStorage
|
||||||
storeData("active-groups-directs", activeData).catch((error) => {
|
storeData("active-groups-directs", activeData).catch((error) => {
|
||||||
console.error("Error saving data:", error);
|
console.error("Error saving data:", error);
|
||||||
@ -2961,10 +2972,10 @@ export const checkNewMessages = async () => {
|
|||||||
) {
|
) {
|
||||||
// Create a unique notification ID with type and group announcement details
|
// Create a unique notification ID with type and group announcement details
|
||||||
const notificationId =
|
const notificationId =
|
||||||
"chat_notification_" +
|
encodeURIComponent("chat_notification_" +
|
||||||
Date.now() +
|
Date.now() +
|
||||||
"_type=group-announcement" +
|
"_type=group-announcement" +
|
||||||
`_from=${newAnnouncements[0]?.groupId}`;
|
`_from=${newAnnouncements[0]?.groupId}`);
|
||||||
|
|
||||||
const title = "New group announcement!";
|
const title = "New group announcement!";
|
||||||
const body = `You have received a new announcement from ${newAnnouncements[0]?.groupName}`;
|
const body = `You have received a new announcement from ${newAnnouncements[0]?.groupName}`;
|
||||||
@ -2984,7 +2995,7 @@ export const checkNewMessages = async () => {
|
|||||||
// Automatically close the notification after 5 seconds if it’s not clicked
|
// Automatically close the notification after 5 seconds if it’s not clicked
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.close();
|
notification.close();
|
||||||
}, 5000); // Close after 5 seconds
|
}, 10000); // Close after 5 seconds
|
||||||
}
|
}
|
||||||
const savedtimestampAfter = await getTimestampGroupAnnouncement();
|
const savedtimestampAfter = await getTimestampGroupAnnouncement();
|
||||||
window.postMessage(
|
window.postMessage(
|
||||||
@ -3113,10 +3124,10 @@ export const checkThreads = async (bringBack) => {
|
|||||||
|
|
||||||
if (newAnnouncements.length > 0) {
|
if (newAnnouncements.length > 0) {
|
||||||
const notificationId =
|
const notificationId =
|
||||||
"chat_notification_" +
|
encodeURIComponent("chat_notification_" +
|
||||||
Date.now() +
|
Date.now() +
|
||||||
"_type=thread-post" +
|
"_type=thread-post" +
|
||||||
`_data=${JSON.stringify(newAnnouncements[0])}`;
|
`_data=${JSON.stringify(newAnnouncements[0])}`);
|
||||||
let isDisableNotifications =
|
let isDisableNotifications =
|
||||||
(await getUserSettings({ key: "disable-push-notifications" })) || false;
|
(await getUserSettings({ key: "disable-push-notifications" })) || false;
|
||||||
if (!isDisableNotifications) {
|
if (!isDisableNotifications) {
|
||||||
@ -3146,7 +3157,7 @@ export const checkThreads = async (bringBack) => {
|
|||||||
// Automatically close the notification after 5 seconds if it’s not clicked
|
// Automatically close the notification after 5 seconds if it’s not clicked
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
notification.close();
|
notification.close();
|
||||||
}, 5000); // Close after 5 seconds
|
}, 10000); // Close after 5 seconds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3187,3 +3198,5 @@ export const checkThreads = async (bringBack) => {
|
|||||||
// // Optional timeout callback
|
// // Optional timeout callback
|
||||||
// BackgroundFetch.finish(taskId);
|
// BackgroundFetch.finish(taskId);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,48 +55,73 @@ async function decryptData(encryptedData: ArrayBuffer, key: CryptoKey, iv: Uint8
|
|||||||
return decoder.decode(decryptedData);
|
return decoder.decode(decryptedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encrypt data, then concatenate the IV and encrypted data for storage
|
// Encode a JSON payload as Base64
|
||||||
|
function jsonToBase64(payload) {
|
||||||
|
const utf8Array = new TextEncoder().encode(JSON.stringify(payload));
|
||||||
|
let binary = '';
|
||||||
|
utf8Array.forEach((byte) => (binary += String.fromCharCode(byte)));
|
||||||
|
return btoa(binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode a Base64 string back to JSON
|
||||||
|
function base64ToJson(base64) {
|
||||||
|
const binary = atob(base64);
|
||||||
|
const bytes = new Uint8Array(binary.length);
|
||||||
|
for (let i = 0; i < binary.length; i++) {
|
||||||
|
bytes[i] = binary.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return JSON.parse(new TextDecoder().decode(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
export const storeData = async (key: string, payload: any): Promise<string> => {
|
export const storeData = async (key: string, payload: any): Promise<string> => {
|
||||||
await initializeKeyAndIV();
|
await initializeKeyAndIV();
|
||||||
|
|
||||||
if (keysToEncrypt.includes(key) && inMemoryKey) {
|
const base64Data = jsonToBase64(payload);
|
||||||
// Encrypt the payload if the key is in keysToEncrypt
|
|
||||||
const { iv, encryptedData } = await encryptData(JSON.stringify(payload), inMemoryKey);
|
|
||||||
|
|
||||||
// Combine IV and encrypted data into a single string
|
if (keysToEncrypt.includes(key) && inMemoryKey) {
|
||||||
|
// Encrypt the Base64-encoded payload
|
||||||
|
const { iv, encryptedData } = await encryptData(base64Data, inMemoryKey);
|
||||||
|
|
||||||
|
// Combine IV and encrypted data into a single Uint8Array
|
||||||
const combinedData = new Uint8Array([...iv, ...new Uint8Array(encryptedData)]);
|
const combinedData = new Uint8Array([...iv, ...new Uint8Array(encryptedData)]);
|
||||||
await SecureStoragePlugin.set({ key, value: btoa(String.fromCharCode(...combinedData)) });
|
const encryptedBase64Data = btoa(String.fromCharCode(...combinedData));
|
||||||
|
await SecureStoragePlugin.set({ key, value: encryptedBase64Data });
|
||||||
} else {
|
} else {
|
||||||
// Store data in plain text if not in keysToEncrypt
|
// Store Base64-encoded data in plain text if not in keysToEncrypt
|
||||||
await SecureStoragePlugin.set({ key, value: JSON.stringify(payload) });
|
await SecureStoragePlugin.set({ key, value: base64Data });
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Data saved successfully";
|
return "Data saved successfully";
|
||||||
};
|
};
|
||||||
|
|
||||||
// Retrieve data, split the IV and encrypted data, then decrypt
|
|
||||||
export const getData = async <T = any>(key: string): Promise<T> => {
|
export const getData = async <T = any>(key: string): Promise<T> => {
|
||||||
await initializeKeyAndIV();
|
await initializeKeyAndIV();
|
||||||
|
|
||||||
const storedDataBase64 = await SecureStoragePlugin.get({ key });
|
const storedDataBase64 = await SecureStoragePlugin.get({ key });
|
||||||
if (storedDataBase64.value) {
|
if (storedDataBase64.value) {
|
||||||
if (keysToEncrypt.includes(key) && inMemoryKey) {
|
if (keysToEncrypt.includes(key) && inMemoryKey) {
|
||||||
// If the key is in keysToEncrypt, decrypt the data
|
// Decode the Base64-encoded encrypted data
|
||||||
const combinedData = atob(storedDataBase64.value).split("").map((c) => c.charCodeAt(0));
|
const combinedData = atob(storedDataBase64.value)
|
||||||
const iv = new Uint8Array(combinedData.slice(0, 12)); // First 12 bytes are the IV
|
.split("")
|
||||||
const encryptedData = new Uint8Array(combinedData.slice(12)).buffer; // The rest is encrypted data
|
.map((c) => c.charCodeAt(0));
|
||||||
|
|
||||||
const decryptedData = await decryptData(encryptedData, inMemoryKey, iv);
|
const iv = new Uint8Array(combinedData.slice(0, 12)); // First 12 bytes are the IV
|
||||||
return JSON.parse(decryptedData) as T;
|
const encryptedData = new Uint8Array(combinedData.slice(12)).buffer;
|
||||||
|
|
||||||
|
const decryptedBase64Data = await decryptData(encryptedData, inMemoryKey, iv);
|
||||||
|
return base64ToJson(decryptedBase64Data);
|
||||||
} else {
|
} else {
|
||||||
// If the key is not in keysToEncrypt, parse data as plain text
|
// Decode non-encrypted data
|
||||||
return JSON.parse(storedDataBase64.value) as T;
|
return base64ToJson(storedDataBase64.value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`No data found for key: ${key}`);
|
throw new Error(`No data found for key: ${key}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Remove keys from storage and log out
|
// Remove keys from storage and log out
|
||||||
export async function removeKeysAndLogout(keys: string[], event: MessageEvent, request: any) {
|
export async function removeKeysAndLogout(keys: string[], event: MessageEvent, request: any) {
|
||||||
try {
|
try {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user