Skip to content

Commit

Permalink
Worked on caching and offline viewing #74
Browse files Browse the repository at this point in the history
  • Loading branch information
YukiGasai committed Feb 28, 2023
1 parent 44fd86b commit 724fd1c
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 37 deletions.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "google-calendar",
"name": "Google Calendar",
"version": "1.8.11",
"version": "1.8.12",
"minAppVersion": "0.12.0",
"description": "Interact with your Google Calendar from Inside Obsidian",
"author": "YukiGasai",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "google-calendar",
"version": "1.8.11",
"version": "1.8.12",
"description": "Interact with your Google Calendar from Inside Obsidian",
"main": "main.js",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion src/googleApi/GoogleColors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const eventColors = new Map<string, string>();
export async function getGoogleColors(): Promise<void> {

if (!settingsAreCompleteAndLoggedIn()) return;

if (calendarColors.size) return;

const colorData = await callRequest(`https://www.googleapis.com/calendar/v3/colors`, "GET", null);

Expand Down
6 changes: 6 additions & 0 deletions src/googleApi/GoogleListCalendars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { callRequest } from "src/helper/RequestWrapper";
import { settingsAreCompleteAndLoggedIn } from "../view/GoogleCalendarSettingTab";

let cachedCalendars: GoogleCalendar[] = []
let lock = false;

/**
* This function is used to filter out all calendars that are on the users blacklist
Expand Down Expand Up @@ -41,6 +42,10 @@ export async function googleListCalendars(): Promise<GoogleCalendar[]> {
return filterCalendarsByBlackList(plugin, cachedCalendars);
}

// Added a lock to prevent multiple requests at the same time
if(lock) return [];
lock = true;

//Make sure the colors for calendar and events are loaded before getting the first calendar
await getGoogleColors();

Expand All @@ -55,5 +60,6 @@ export async function googleListCalendars(): Promise<GoogleCalendar[]> {

const calendars = filterCalendarsByBlackList(plugin, calendarList.items);

lock = false;
return calendars;
}
84 changes: 67 additions & 17 deletions src/googleApi/GoogleListEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,52 @@ function resolveMultiDayEventsHelper(
return totalEventList;
}

// Check if the range if events is already cached
function checkForCachedEvents (
plugin: GoogleCalendarPlugin,
GoogleCalendar: GoogleCalendar,
startDate: moment.Moment,
endDate: moment.Moment
) : GoogleEvent[] | null {

let currentDate = startDate.clone();
let cachedEventList: GoogleEvent[] = [];

// Loop through all days and check if there is a cached result
while (currentDate <= endDate) {

const cacheKey: string = JSON.stringify({
day: currentDate.format("YYYY-MM-DD"),
calendar: GoogleCalendar.id
});

// Check if there is a day missing in the cache
if(!cachedEvents.has(cacheKey)) {
return null;
}

if(!plugin.settings.useCustomClient && plugin.settings.refreshInterval < 60){
plugin.settings.refreshInterval = 60;
}

// Get the cached events and check if they are still valid
const { events, updated } = cachedEvents.get(cacheKey);
if (updated.clone().add(plugin.settings.refreshInterval, "second").isBefore(window.moment())) {
return null
}

// Add the events to the list
cachedEventList = [...cachedEventList, ...events];

// Check the next day
currentDate.add(1, "day");

}

return cachedEventList;
}


/**
* This function will return a list of event in a timespan from a specific calendar
* The function will check for an equal function call in the cache if there is a stored result that is not to old it will return without api request
Expand All @@ -216,32 +262,36 @@ async function googleListEventsByCalendar(
endDate: moment.Moment
): Promise<GoogleEvent[]> {

//Turn dates into strings for request and caching
const startString = startDate.toISOString();
const endString = endDate.toISOString();

//get the hashmap key from start end and calendar
const cacheKey: string = JSON.stringify({ start: startString, end: endString, calendar: GoogleCalendar.id });

//Check if cache has request saved
if (cachedEvents.has(cacheKey)) {
const { events, updated } = cachedEvents.get(cacheKey);
if (updated.clone().add(plugin.settings.refreshInterval, "second").isAfter(window.moment())) {
return events;
}
//Check if the events are already cached and return them if they are
const alreadyCachedEvents = checkForCachedEvents(plugin, GoogleCalendar, startDate, endDate)
if(alreadyCachedEvents) {
return alreadyCachedEvents;
}

//Get the events because cache was no option
let totalEventList: GoogleEvent[] = await requestEventsFromApi(GoogleCalendar, startString, endString);
let totalEventList: GoogleEvent[] = await requestEventsFromApi(GoogleCalendar, startDate.toISOString(), endDate.toISOString());

//Turn multi day events into multiple events
totalEventList = resolveMultiDayEventsHelper(totalEventList, startDate, endDate);

//Filter out original multi day event
totalEventList = totalEventList.filter((indexEvent: GoogleEvent) => indexEvent.eventType !== "delete");

//Cache result
cachedEvents.set(cacheKey, { events: totalEventList, updated: window.moment() })
// Group events by Day
const groupedEvents = _.groupBy(totalEventList, (event: GoogleEvent) => {
const startMoment = window.moment(event.start.dateTime);
return startMoment.format("YYYY-MM-DD");
});

const currentDate = startDate.clone();
while (currentDate <= endDate) {
const formattedDate = currentDate.format("YYYY-MM-DD");

const cacheKey: string = JSON.stringify({ day: formattedDate, calendar: GoogleCalendar.id });
cachedEvents.set(cacheKey, { events: groupedEvents[formattedDate] || [], updated: window.moment() })

currentDate.add(1, "day");
}

return totalEventList;
}
33 changes: 18 additions & 15 deletions src/helper/RequestWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const callRequest = async (url: string, method: string, body: any, noAuth
headers: requestHeaders
})

if (response.status >= 400) {
if (response.status >= 300) {
return;
}

Expand All @@ -45,22 +45,25 @@ export const callRequest = async (url: string, method: string, body: any, noAuth


//Normal request
const response = await requestUrl({
method: method,
url: url,
body: body ? JSON.stringify(body) : null,
headers: requestHeaders
});
try{
const response = await requestUrl({
method: method,
url: url,
body: body ? JSON.stringify(body) : null,
headers: requestHeaders,
throw: true
});

if (response.status >= 300) {
return;
}

if (response.status >= 400) {
return;
}
if (method.toLowerCase() == "delete") {
return { status: "success" };
}

if (method.toLowerCase() == "delete") {
return { status: "success" };
return (await response.json);
}catch(err){
return;
}

return (await response.json);

}
1 change: 0 additions & 1 deletion src/svelte/ScheduleComp.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
//only reload if events change
if(JSON.stringify(newEvents) == JSON.stringify(events)){
loading = false;
return;
}
days.clear();
Expand Down
6 changes: 5 additions & 1 deletion src/view/GoogleCalendarSettingTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export class GoogleCalendarSettingTab extends PluginSettingTab {
toggle
.setValue(this.plugin.settings.useCustomClient)
.onChange(async (value) => {
setRefreshToken("");
setAccessToken("");
setExpirationTime(0);
this.plugin.settings.useCustomClient = value;
await this.plugin.saveSettings();
this.display();
Expand Down Expand Up @@ -139,9 +142,10 @@ export class GoogleCalendarSettingTab extends PluginSettingTab {
.setDesc("Time in seconds between refresh request from google server")
.addSlider(cb => {
cb.setValue(this.plugin.settings.refreshInterval)
cb.setLimits(10, 360, 1);
cb.setLimits(this.plugin.settings.useCustomClient ? 10 : 60, 360, 1);
cb.setDynamicTooltip();
cb.onChange(async value => {
if(value < 60 && !this.plugin.settings.useCustomClient)return;
this.plugin.settings.refreshInterval = value;
await this.plugin.saveSettings();
})
Expand Down

0 comments on commit 724fd1c

Please sign in to comment.