Skip to content

Commit

Permalink
Implements customize automatic syncing #2
Browse files Browse the repository at this point in the history
  • Loading branch information
Scarvy committed Nov 17, 2024
1 parent b25e1da commit 4140783
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 15 deletions.
51 changes: 47 additions & 4 deletions src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,29 @@ const createWindow = () => {
console.log('User is authenticated: ', tokenExsits)
mainWindow.webContents.once('did-finish-load', () => {
mainWindow.webContents.send('login-status', tokenExsits)
if (tokenExsits) {

// Configure scheduled sync
const syncFrequency = store.get('syncFrequency') || '0' // default to manual
configureScheduledSync(syncFrequency)

// if token exists check if the user has set to sync on startup
const triggerOnLoad = Boolean(store.get('triggerOnLoad'))
console.log('Trigger on load: ', triggerOnLoad)
if (triggerOnLoad) {
// if sync is already in progress, don't start another one
if (Boolean(store.get('isSyncing'))) {
mainWindow.webContents.send('toast:show', { variant: 'default', message: 'Sync already in progress...'})
console.log('Sync already in progress')
return
}

mainWindow.webContents.send('toast:show', { variant: 'default', message: 'Initiating sync...'})
const readwiseSync = new ReadwiseSync(mainWindow, store)
readwiseSync.syncHighlights(undefined, true)
console.log('Syncing highlights on load')
}
}
})

// Open external links in the default browser
Expand Down Expand Up @@ -61,9 +84,19 @@ ipcMain.on('electron-store-set', async (_, key, value) => {
store.set(key, value)
})

ipcMain.handle('sync-highlights', () => {
ipcMain.handle('sync-highlights', (_event, auto?: boolean) => {

// if sync is already in progress, don't start another one
if (Boolean(store.get('isSyncing'))) {
mainWindow.webContents.send('toast:show', { variant: 'default', message: 'Sync already in progress...'})
console.log('Sync already in progress')
return
}

mainWindow.webContents.send('toast:show', { variant: 'default', message: 'Initiating sync...'})

const readwiseSync = new ReadwiseSync(mainWindow, store)
return readwiseSync.syncHighlights()
return readwiseSync.syncHighlights(undefined, auto)
})

ipcMain.handle('connect-to-readwise', async (event: Electron.Event) => {
Expand Down Expand Up @@ -95,14 +128,24 @@ ipcMain.handle('fetch-apple-notes-accounts', async () => {
return await updateAppleNotesAccounts()
})

async function configureScheduledSync() {
const minutes = parseInt(store.get('frequency'))
ipcMain.handle('update-sync-frequency', async (_event, frequency: string) => {
return await configureScheduledSync(frequency)
})

async function configureScheduledSync(frequency: string) {
const minutes = parseInt(frequency)
let milliseconds = minutes * 60 * 1000 // convert minutes to milliseconds
console.log("Settings interval to ", milliseconds)
if (!milliseconds) {
// user set frequency to "Manual"
return '0'
}
setInterval(async () => {
console.log('Syncing highlights...', new Date())
const readwiseSync = new ReadwiseSync(mainWindow, store)
await readwiseSync.syncHighlights(undefined, true)
}, milliseconds)
return frequency
}

// Quit when all windows are closed, except on macOS. There, it's common
Expand Down
17 changes: 17 additions & 0 deletions src/main/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,14 @@ export class ReadwiseSync {

if (!notesFolder) {
console.log('Readwise Official plugin: no folder selected')
this.mainWindow.webContents.send('toast:show', { variant: 'destructive', message: 'No folder selected' })
await this.handleSyncError('Sync failed')
return
}

if (!account) {
console.log('Readwise Official plugin: no account selected')
this.mainWindow.webContents.send('toast:show', { variant: 'destructive', message: 'No account selected' })
await this.handleSyncError('Sync failed')
return
}
Expand Down Expand Up @@ -207,6 +209,7 @@ export class ReadwiseSync {
await this.acknowledgeSyncCompleted()
await this.handleSyncSuccess('Synced', exportID)
this.mainWindow.webContents.send('syncing-complete')
this.mainWindow.webContents.send('toast:show', { variant: 'success', message: 'Sync completed' })
console.log('Readwise Official plugin: Synced!', exportID)
console.log('Readwise Official plugin: completed sync')
}
Expand Down Expand Up @@ -280,9 +283,11 @@ export class ReadwiseSync {
console.log(`Exporting Readwise data (${data.booksExported} / ${data.totalBooks}) ...`)
this.mainWindow.webContents.send('export-pending', false)
this.mainWindow.webContents.send('export-progress', data)
this.mainWindow.webContents.send('toast:show', { variant: 'default', message: `Exporting Readwise data (${data.booksExported} / ${data.totalBooks}` })
} else {
console.log('Building export...')
this.mainWindow.webContents.send('export-pending', true)
this.mainWindow.webContents.send('toast:show', { variant: 'default', message: 'Building export...' })
}

// wait 1 second
Expand All @@ -291,10 +296,13 @@ export class ReadwiseSync {
await this.getExportStatus(statusID, token, uuid)
} else if (SUCCESS_STATUSES.includes(data.taskStatus)) {
this.mainWindow.webContents.send('export-complete', {})
this.mainWindow.webContents.send('toast:show', { variant: 'success', message: 'Export completed' })
console.log('Export completed')
await this.downloadExport(statusID)
} else {
console.log('Readwise Official plugin: unknown status in getExportStatus: ', data)
this.mainWindow.webContents.send('export-error', 'Sync failed')
this.mainWindow.webContents.send('toast:show', { variant: 'destructive', message: 'Sync failed' })
await this.handleSyncError('Sync failed')
return
}
Expand Down Expand Up @@ -343,6 +351,7 @@ export class ReadwiseSync {
async queueExport(statusId?: number, auto?: boolean): Promise<string> {
if (this.store.get('isSyncing')) {
console.log('Readwise sync already in progress')
this.mainWindow.webContents.send('toast:show', { variant: 'default', message: 'Sync already in progress' })
return 'Sync already in progress'
}

Expand All @@ -356,12 +365,14 @@ export class ReadwiseSync {

if (!readwiseDir) {
console.log('Readwise Official plugin: no folder selected')
this.mainWindow.webContents.send('toast:show', { variant: 'destructive', message: 'No folder selected' })
await this.handleSyncError('Sync failed')
return 'Sync failed'
}

if (!account) {
console.log('Readwise Official plugin: no account selected')
this.mainWindow.webContents.send('toast:show', { variant: 'destructive', message: 'No account selected' })
await this.handleSyncError('Sync failed')
return 'Sync failed'
}
Expand All @@ -383,6 +394,7 @@ export class ReadwiseSync {
if (!folderCreated) {
console.log('Readwise Official plugin: failed to create folder')
await this.handleSyncError('Sync failed')
this.mainWindow.webContents.send('toast:show', { variant: 'destructive', message: 'Error: Failed to create folder' })
return 'Sync failed'
} else {
console.log('Readwise Official plugin: folder created')
Expand Down Expand Up @@ -418,6 +430,7 @@ export class ReadwiseSync {
} catch (e) {
console.log('Readwise Official plugin: fetch failed in queueExport: ', e)
await this.handleSyncError('Sync failed')
this.mainWindow.webContents.send('toast:show', { variant: 'destructive', message: 'Synced failed' })
return 'Sync failed'
}

Expand All @@ -428,6 +441,7 @@ export class ReadwiseSync {
if (!data) {
console.log('Readwise Official plugin: no data in queueExport')
await this.handleSyncError('Sync failed')
this.mainWindow.webContents.send('toast:show', { variant: 'destructive', message: 'Synced failed' })
return 'Sync failed'
}

Expand All @@ -436,6 +450,7 @@ export class ReadwiseSync {
if (data.latest_id <= lastest_id) {
await this.handleSyncSuccess() // Data is already up to date
console.log('Readwise data is already up to date')
this.mainWindow.webContents.send('toast:show', { variant: 'success', message: 'Data is already up to date' })
return 'Data is already up to date'
}

Expand All @@ -454,11 +469,13 @@ export class ReadwiseSync {
'Latest Readwise sync already happended on your other device. Data should be up to date: ',
response
)
this.mainWindow.webContents.send('toast:show', { variant: 'success', message: 'Data is already up to date' })
return 'Data is already up to date'
}
} else {
console.log('Readwise Official plugin: bad response in queueExport: ', response)
await this.handleSyncError(this.getErrorMessageFromResponse(response))
this.mainWindow.webContents.send('toast:show', { variant: 'destructive', message: 'Synced failed. Please try again.' })
return 'Sync failed'
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/preload/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ declare global {
readwise: {
syncHighlights: () => Promise<string>;
openCustomFormatWindow: () => void;
connectToReadwise: () => Promise<string>;
updateSyncFrequency: (frequency: string) => Promise<string>;
};
};
}
Expand Down
3 changes: 3 additions & 0 deletions src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ contextBridge.exposeInMainWorld('api', {
syncHighlights() {
return ipcRenderer.invoke('sync-highlights')
},
updateSyncFrequency(frequency: string) {
return ipcRenderer.invoke('update-sync-frequency', frequency)
},
openCustomFormatWindow() {
ipcRenderer.invoke('open-custom-format-window')
}
Expand Down
13 changes: 4 additions & 9 deletions src/renderer/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ import { Toaster } from './components/ui/toaster'
import { LoginCard } from './components/login'
import { SettingsOptions } from './components/settings-options'
import { SyncingProgress } from './components/syncing-progress'
import { useToast } from './hooks/use-toast'

export default function App() {
const { toast } = useToast()

const [isLoggedIn, setIsLoggedIn] = useState(false)
const [isSyncing, setIsSyncing] = useState(false)

Expand All @@ -19,15 +16,13 @@ export default function App() {
useEffect(() => {
checkLoginStatus()

window.api.on('login-status', (event, loggedIn) => {
window.api.on('login-status', (_event, loggedIn: boolean) => {
setIsLoggedIn(loggedIn)

if (loggedIn) {
toast({
variant: 'success',
description: 'Successfully connected to Readwise',
duration: 5000
})
console.log('Logged in')
} else {
console.log('Logged out')
}
})

Expand Down
24 changes: 22 additions & 2 deletions src/renderer/components/settings-options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@ export function SettingsOptions({ onIsSyncing }: SettingsOptionsProps) {
})
}

const handleFrequencyChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
const handleFrequencyChange = async (e: React.ChangeEvent<HTMLSelectElement>) => {
const selectedFrequency = e.target.value
setSyncFrequency(selectedFrequency)
saveFrequency(selectedFrequency)
const msg = await window.api.readwise.updateSyncFrequency(selectedFrequency)
console.log('Sync frequency updated to: ', msg)
toast({
variant: 'default',
description: 'Sync frequency updated to "' + frequencyOptions.find((f) => f.value === selectedFrequency)?.label + '"',
Expand All @@ -103,7 +105,7 @@ export function SettingsOptions({ onIsSyncing }: SettingsOptionsProps) {
async function handleSyncHighlights() {
onIsSyncing(true) // Start syncing
try {
const msg = await window.api.readwise.syncHighlights()
const msg = await window.api.readwise.syncHighlights(undefined, false)
toast({
variant: 'success',
description: msg,
Expand All @@ -127,6 +129,24 @@ export function SettingsOptions({ onIsSyncing }: SettingsOptionsProps) {
window.api.readwise.openCustomFormatWindow()
}

useEffect(() => {
async function handleSyncProgressMessages(_event, data) {
console.log('Sync progress', data.message)
// if toast already on screen, clear it and show the new one
toast({
variant: data.variant,
description: data.message,
duration: 5000
})
}

window.api.on('toast:show', handleSyncProgressMessages)

return () => {
window.api.removeAllListeners('toast:show')
}
}, [])

return (
<>
<div className="mb-2">
Expand Down

0 comments on commit 4140783

Please sign in to comment.