From f526bcb293f2aedcb438d631be46d11213a6afdb Mon Sep 17 00:00:00 2001 From: Ramzan Date: Tue, 18 Aug 2020 19:12:52 -0400 Subject: [PATCH] SyncGate: create auto-generated SyncInfoJournal of address book birtdays --- src/Settings/index.tsx | 15 +++++++++++ src/SyncGate.tsx | 58 +++++++++++++++++++++++++++++++++++++++--- src/store/reducers.ts | 1 + 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/Settings/index.tsx b/src/Settings/index.tsx index 232d5ea..f11baca 100644 --- a/src/Settings/index.tsx +++ b/src/Settings/index.tsx @@ -43,6 +43,7 @@ export default React.memo(function Settings() { const settings = useSelector((state: StoreState) => state.settings); const darkMode = !!settings.darkMode; + const hideBirthdayCalendar = !!settings.hideBirthdayCalendar; function handleChange(event: React.ChangeEvent) { const name = event.target.name; @@ -85,7 +86,21 @@ export default React.memo(function Settings() { label="Dark mode" /> +

Birthday calendar

+ + dispatch(setSettings({ ...settings, hideBirthdayCalendar: !hideBirthdayCalendar }))} + /> + } + label="Hide birthday calendar" + /> + ); }); + diff --git a/src/SyncGate.tsx b/src/SyncGate.tsx index b6a62c8..6b4f925 100644 --- a/src/SyncGate.tsx +++ b/src/SyncGate.tsx @@ -26,6 +26,9 @@ import { CURRENT_VERSION } from "etesync"; import { store, JournalsData, EntriesData, StoreState, CredentialsData, UserInfoData } from "./store"; import { addJournal, fetchAll, fetchEntries, fetchUserInfo, createUserInfo } from "./store/actions"; +import { syncEntriesToItemMap } from "./journal-processors"; +import { ContactType } from "./pim-types"; +import { parseDate } from "./helpers"; export interface SyncInfoJournal { journal: EteSync.Journal; @@ -45,6 +48,7 @@ interface SelectorProps { journals: JournalsData; entries: EntriesData; userInfo: UserInfoData; + hideBirthdays?: boolean; } const syncInfoSelector = createSelector( @@ -52,7 +56,8 @@ const syncInfoSelector = createSelector( (props: SelectorProps) => props.journals!, (props: SelectorProps) => props.entries, (props: SelectorProps) => props.userInfo, - (etesync, journals, entries, userInfo) => { + (props: SelectorProps) => props.hideBirthdays, + (etesync, journals, entries, userInfo, hideBirthdays) => { const derived = etesync.encryptionKey; const userInfoCryptoManager = userInfo.getCryptoManager(etesync.encryptionKey); try { @@ -65,7 +70,9 @@ const syncInfoSelector = createSelector( } } - return journals.reduce( + let bdayEntries = List(); + + let syncInfo = journals.reduce( (ret, journal) => { const journalEntries = entries.get(journal.uid); let prevUid: string | null = null; @@ -86,6 +93,30 @@ const syncInfoSelector = createSelector( return syncEntry; }); + if ((collectionInfo.type === "ADDRESS_BOOK") && !hideBirthdays) { + let addressBookItems: {[key: string]: ContactType} = {}; + addressBookItems = syncEntriesToItemMap(collectionInfo, syncEntries, addressBookItems); + + Object.values(addressBookItems).filter((c) => c.bday).forEach((c) => { + const bdayTime = parseDate(c.comp.getFirstProperty("bday")); + if (bdayTime === {} || bdayTime.month === undefined) { + return; + } + const year = bdayTime.year ?? 1900; + const month = (bdayTime.month + 1).toString().padStart(2, "0"); + const day = bdayTime.day.toString().padStart(2, "0"); + + const content = + "BEGIN:VCALENDAR\nBEGIN:VEVENT\n" + + `SUMMARY:${c.fn}'s Birthday\n` + + `UID:${journal.uid}${c.uid}\n` + + `DTSTART;VALUE=DATE:${year}${month}${day}\n` + + "RRULE:FREQ=YEARLY\nEND:VEVENT\nEND:VCALENDAR"; + + bdayEntries = bdayEntries.push({ action: EteSync.SyncEntryAction.Add, content }); + }); + } + return ret.set(journal.uid, { entries: syncEntries, collection: collectionInfo, @@ -95,6 +126,27 @@ const syncInfoSelector = createSelector( }, Map() ); + + if (!hideBirthdays) { + const bdayCollection = new EteSync.CollectionInfo(); + bdayCollection.uid = "birthdays"; + bdayCollection.type = "CALENDAR"; + bdayCollection.displayName = "Birthdays"; + bdayCollection.color = -1413414; + + const bdayJournal = new EteSync.Journal({ uid: bdayCollection.uid, readOnly: true }); + const cryptoManager = new EteSync.CryptoManager(etesync.encryptionKey, bdayCollection.uid); + bdayJournal.setInfo(cryptoManager, bdayCollection); + + syncInfo = syncInfo.set("birthdays", { + journal: bdayJournal, + journalEntries: List(), + collection: bdayCollection, + entries: bdayEntries, + }); + } + + return syncInfo; } ); @@ -186,7 +238,7 @@ export default withRouter(function SyncGate(props: RouteComponentProps<{}> & Pro moment.locale(settings.locale); - const journalMap = syncInfoSelector({ etesync, userInfo, journals, entries }); + const journalMap = syncInfoSelector({ etesync, userInfo, journals, entries, hideBirthdays: settings.hideBirthdayCalendar }); return ( diff --git a/src/store/reducers.ts b/src/store/reducers.ts index 29edabc..2177be2 100644 --- a/src/store/reducers.ts +++ b/src/store/reducers.ts @@ -273,6 +273,7 @@ export const errorsReducer = handleActions( export interface SettingsType { locale: string; darkMode?: boolean; + hideBirthdayCalendar?: boolean; taskSettings: { filterBy: string | null; sortBy: string;