2021-03-14 20:10:48 -07:00
|
|
|
import { CollectionBase } from "../../Contracts/ViewModels";
|
2020-05-25 21:30:55 -05:00
|
|
|
import { StorageKey, LocalStorageUtility } from "../../Shared/StorageUtility";
|
2021-03-14 20:10:48 -07:00
|
|
|
import { NotebookContentItem } from "../Notebook/NotebookContentItem";
|
2020-05-25 21:30:55 -05:00
|
|
|
|
|
|
|
export enum Type {
|
|
|
|
OpenCollection,
|
2021-01-20 09:15:01 -06:00
|
|
|
OpenNotebook,
|
2020-05-25 21:30:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface OpenNotebookItem {
|
2021-03-14 20:10:48 -07:00
|
|
|
type: Type.OpenNotebook;
|
2020-05-25 21:30:55 -05:00
|
|
|
name: string;
|
|
|
|
path: string;
|
|
|
|
}
|
|
|
|
|
2020-10-13 13:29:39 -07:00
|
|
|
export interface OpenCollectionItem {
|
2021-03-14 20:10:48 -07:00
|
|
|
type: Type.OpenCollection;
|
2020-10-13 13:29:39 -07:00
|
|
|
databaseId: string;
|
|
|
|
collectionId: string;
|
|
|
|
}
|
2020-05-25 21:30:55 -05:00
|
|
|
|
2021-03-14 20:10:48 -07:00
|
|
|
type Item = OpenNotebookItem | OpenCollectionItem;
|
2020-05-25 21:30:55 -05:00
|
|
|
|
|
|
|
// Update schemaVersion if you are going to change this interface
|
|
|
|
interface StoredData {
|
|
|
|
schemaVersion: string;
|
|
|
|
itemsMap: { [accountId: string]: Item[] }; // FIFO
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores most recent activity
|
|
|
|
*/
|
2021-03-03 01:24:08 -08:00
|
|
|
class MostRecentActivity {
|
2021-03-14 20:10:48 -07:00
|
|
|
private static readonly schemaVersion: string = "2";
|
2020-05-25 21:30:55 -05:00
|
|
|
private static itemsMaxNumber: number = 5;
|
|
|
|
private storedData: StoredData;
|
2021-03-03 01:24:08 -08:00
|
|
|
constructor() {
|
2020-05-25 21:30:55 -05:00
|
|
|
// Retrieve from local storage
|
|
|
|
if (LocalStorageUtility.hasItem(StorageKey.MostRecentActivity)) {
|
|
|
|
const rawData = LocalStorageUtility.getEntryString(StorageKey.MostRecentActivity);
|
|
|
|
|
|
|
|
if (!rawData) {
|
|
|
|
this.storedData = MostRecentActivity.createEmptyData();
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
this.storedData = JSON.parse(rawData);
|
|
|
|
} catch (e) {
|
|
|
|
console.error("Unable to parse stored most recent activity. Use empty data:", rawData);
|
|
|
|
this.storedData = MostRecentActivity.createEmptyData();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If version doesn't match or schema broke, nuke it!
|
|
|
|
if (
|
|
|
|
!this.storedData.hasOwnProperty("schemaVersion") ||
|
|
|
|
this.storedData["schemaVersion"] !== MostRecentActivity.schemaVersion
|
|
|
|
) {
|
|
|
|
LocalStorageUtility.removeEntry(StorageKey.MostRecentActivity);
|
|
|
|
this.storedData = MostRecentActivity.createEmptyData();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.storedData = MostRecentActivity.createEmptyData();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let p in this.storedData.itemsMap) {
|
|
|
|
this.cleanupItems(p);
|
|
|
|
}
|
|
|
|
this.saveToLocalStorage();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static createEmptyData(): StoredData {
|
|
|
|
return {
|
|
|
|
schemaVersion: MostRecentActivity.schemaVersion,
|
2021-01-20 09:15:01 -06:00
|
|
|
itemsMap: {},
|
2020-05-25 21:30:55 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
private static isEmpty(object: any) {
|
|
|
|
return Object.keys(object).length === 0 && object.constructor === Object;
|
|
|
|
}
|
|
|
|
|
|
|
|
private saveToLocalStorage() {
|
|
|
|
if (MostRecentActivity.isEmpty(this.storedData.itemsMap)) {
|
|
|
|
if (LocalStorageUtility.hasItem(StorageKey.MostRecentActivity)) {
|
|
|
|
LocalStorageUtility.removeEntry(StorageKey.MostRecentActivity);
|
|
|
|
}
|
|
|
|
// Don't save if empty
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LocalStorageUtility.setEntryString(StorageKey.MostRecentActivity, JSON.stringify(this.storedData));
|
|
|
|
}
|
|
|
|
|
2021-03-14 20:10:48 -07:00
|
|
|
private addItem(accountId: string, newItem: Item): void {
|
2020-05-25 21:30:55 -05:00
|
|
|
// When debugging, accountId is "undefined": most recent activity cannot be saved by account. Uncomment to disable.
|
|
|
|
// if (!accountId) {
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// Remove duplicate
|
|
|
|
MostRecentActivity.removeDuplicate(newItem, this.storedData.itemsMap[accountId]);
|
|
|
|
|
|
|
|
this.storedData.itemsMap[accountId] = this.storedData.itemsMap[accountId] || [];
|
|
|
|
this.storedData.itemsMap[accountId].unshift(newItem);
|
|
|
|
this.cleanupItems(accountId);
|
|
|
|
this.saveToLocalStorage();
|
|
|
|
}
|
|
|
|
|
|
|
|
public getItems(accountId: string): Item[] {
|
|
|
|
return this.storedData.itemsMap[accountId] || [];
|
|
|
|
}
|
|
|
|
|
2021-03-14 20:10:48 -07:00
|
|
|
public collectionWasOpened(accountId: string, { id, databaseId }: Pick<CollectionBase, "id" | "databaseId">) {
|
|
|
|
const collectionId = id();
|
|
|
|
this.addItem(accountId, {
|
|
|
|
type: Type.OpenCollection,
|
|
|
|
databaseId,
|
|
|
|
collectionId,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public notebookWasItemOpened(accountId: string, { name, path }: Pick<NotebookContentItem, "name" | "path">) {
|
|
|
|
this.addItem(accountId, {
|
|
|
|
type: Type.OpenNotebook,
|
|
|
|
name,
|
|
|
|
path,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-05-25 21:30:55 -05:00
|
|
|
public clear(accountId: string): void {
|
|
|
|
delete this.storedData.itemsMap[accountId];
|
|
|
|
this.saveToLocalStorage();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find items by doing strict comparison and remove from array if duplicate is found
|
|
|
|
* @param item
|
|
|
|
*/
|
|
|
|
private static removeDuplicate(item: Item, itemsArray: Item[]): void {
|
|
|
|
if (!itemsArray) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let index = -1;
|
|
|
|
for (let i = 0; i < itemsArray.length; i++) {
|
|
|
|
const currentItem = itemsArray[i];
|
2021-03-14 20:10:48 -07:00
|
|
|
if (JSON.stringify(currentItem) === JSON.stringify(item)) {
|
2020-05-25 21:30:55 -05:00
|
|
|
index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
itemsArray.splice(index, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove unknown types
|
|
|
|
* Limit items to max number
|
|
|
|
*/
|
|
|
|
private cleanupItems(accountId: string): void {
|
|
|
|
if (!this.storedData.itemsMap.hasOwnProperty(accountId)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const itemsArray = this.storedData.itemsMap[accountId]
|
2021-01-20 09:15:01 -06:00
|
|
|
.filter((item) => item.type in Type)
|
2020-05-25 21:30:55 -05:00
|
|
|
.slice(0, MostRecentActivity.itemsMaxNumber);
|
|
|
|
if (itemsArray.length === 0) {
|
|
|
|
delete this.storedData.itemsMap[accountId];
|
|
|
|
} else {
|
|
|
|
this.storedData.itemsMap[accountId] = itemsArray;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-03 01:24:08 -08:00
|
|
|
|
|
|
|
export const mostRecentActivity = new MostRecentActivity();
|