9
9
Plugin ,
10
10
PluginSettingTab ,
11
11
Setting ,
12
+ TFile ,
12
13
Vault
13
14
} from 'obsidian' ;
14
15
import * as zip from "@zip.js/zip.js" ;
@@ -47,6 +48,7 @@ interface ReadwisePluginSettings {
47
48
booksToRefresh : Array < string > ;
48
49
booksIDsMap : { [ key : string ] : string ; } ;
49
50
reimportShowConfirmation : boolean ;
51
+ frontmatterBookIdKey ?: string ;
50
52
}
51
53
52
54
// define our initial settings
@@ -65,6 +67,73 @@ const DEFAULT_SETTINGS: ReadwisePluginSettings = {
65
67
reimportShowConfirmation : true ,
66
68
} ;
67
69
70
+ class AdvancedModal extends Modal {
71
+ plugin : ReadwisePlugin ;
72
+
73
+ constructor ( app : App , plugin : ReadwisePlugin ) {
74
+ super ( app ) ;
75
+ this . plugin = plugin ;
76
+ }
77
+
78
+ onOpen ( ) {
79
+ const { titleEl, contentEl } = this ;
80
+
81
+ titleEl . setText ( 'Advanced settings' ) ;
82
+
83
+ // add new setting that allows text input
84
+ new Setting ( contentEl )
85
+ . setName ( 'Book ID frontmatter key' )
86
+ . setDesc ( 'The frontmatter key used to store the Readwise book_id. If set, will be preferred for syncs.' )
87
+ . addText ( text => text
88
+ . setPlaceholder ( 'readwise-book-id' )
89
+ . setValue ( this . plugin . settings . frontmatterBookIdKey )
90
+ . onChange ( async value => {
91
+ console . log ( 'Readwise Official plugin: setting frontmatter book ID key to' , value ) ;
92
+ this . plugin . settings . frontmatterBookIdKey = value ;
93
+ this . plugin . saveSettings ( ) ;
94
+
95
+ // enable/disable populate button depending on whether the key is set
96
+ const populateButton = contentEl . querySelector ( '.rw-setting-populate-book-id' ) ;
97
+ if ( populateButton instanceof HTMLButtonElement ) {
98
+ populateButton . disabled = ! value ;
99
+ }
100
+ } ) ) ;
101
+
102
+ // button to populate the frontmatter with using
103
+ // the frontmatterBookIdKey and matching it
104
+ // with whatever's saved in booksIDsMap
105
+ return new Setting ( contentEl )
106
+ . setName ( 'Populate frontmatter key' )
107
+ . setDesc ( 'If the book ID frontmatter key is configured above, this will populate the frontmatter key setting with the first key found in the booksIDsMap. This will not overwrite existing keys.' )
108
+ . addButton ( button => button
109
+ . setButtonText ( 'Populate' )
110
+ . setClass ( 'rw-setting-populate-book-id' )
111
+ . setDisabled ( ! this . plugin . settings . frontmatterBookIdKey )
112
+ . onClick ( async ( ) => {
113
+ this . plugin . notice ( "Populating frontmatter with book IDs..." , true ) ;
114
+ console . log ( `Readwise Official plugin: populating frontmatter key ${ this . plugin . settings . frontmatterBookIdKey } with matching value from booksIDsMap...` ) ;
115
+
116
+ const readwiseExports = this . plugin . app . vault . getMarkdownFiles ( ) ;
117
+ for ( const file of readwiseExports ) {
118
+ console . log ( 'Readwise Official plugin: checking file for frontmatter' , file . path ) ;
119
+
120
+ const bookId = this . plugin . settings . booksIDsMap [ file . path ] ;
121
+ if ( ! bookId ) continue ;
122
+
123
+ await this . plugin . writeBookIdToFrontmatter ( file , bookId ) ;
124
+ }
125
+
126
+ this . plugin . notice ( "Frontmatter populated with book IDs" , true ) ;
127
+ } )
128
+ ) ;
129
+ }
130
+
131
+ onClose ( ) {
132
+ const { contentEl } = this ;
133
+ contentEl . empty ( ) ;
134
+ }
135
+ }
136
+
68
137
export default class ReadwisePlugin extends Plugin {
69
138
settings : ReadwisePluginSettings ;
70
139
fs : DataAdapter ;
@@ -293,6 +362,7 @@ export default class ReadwisePlugin extends Plugin {
293
362
contentToSave = existingContent + contents ;
294
363
}
295
364
await this . fs . write ( originalName , contentToSave ) ;
365
+ this . app . metadataCache . trigger ( 'readwise:write' ) ;
296
366
await this . saveSettings ( ) ;
297
367
} catch ( e ) {
298
368
console . log ( `Readwise Official plugin: error writing ${ processedFileName } :` , e ) ;
@@ -407,8 +477,10 @@ export default class ReadwisePlugin extends Plugin {
407
477
let booksToRefresh = this . settings . booksToRefresh ;
408
478
this . settings . booksToRefresh = booksToRefresh . filter ( n => ! [ bookId ] . includes ( n ) ) ;
409
479
this . saveSettings ( ) ;
410
- vault . delete ( vault . getAbstractFileByPath ( fileName ) ) ;
411
- this . startSync ( ) ;
480
+ vault . delete ( vault . getAbstractFileByPath ( fileName ) ) . then ( ( ) => {
481
+ this . startSync ( ) ;
482
+ this . app . metadataCache . trigger ( 'readwise:write' ) ;
483
+ } ) ;
412
484
} else {
413
485
this . notice ( "Failed to reimport. Please try again" , true ) ;
414
486
}
@@ -445,6 +517,7 @@ export default class ReadwisePlugin extends Plugin {
445
517
) ;
446
518
447
519
this . refreshBookExport ( this . settings . booksToRefresh ) ;
520
+
448
521
this . app . vault . on ( "delete" , async ( file ) => {
449
522
const bookId = this . settings . booksIDsMap [ file . path ] ;
450
523
if ( bookId ) {
@@ -454,6 +527,7 @@ export default class ReadwisePlugin extends Plugin {
454
527
delete this . settings . booksIDsMap [ file . path ] ;
455
528
this . saveSettings ( ) ;
456
529
} ) ;
530
+
457
531
this . app . vault . on ( "rename" , ( file , oldPath ) => {
458
532
const bookId = this . settings . booksIDsMap [ oldPath ] ;
459
533
if ( ! bookId ) {
@@ -463,6 +537,13 @@ export default class ReadwisePlugin extends Plugin {
463
537
delete this . settings . booksIDsMap [ oldPath ] ;
464
538
this . saveSettings ( ) ;
465
539
} ) ;
540
+
541
+ this . app . metadataCache . on ( 'changed' , async ( file ) => {
542
+ if ( file . path . startsWith ( this . settings . readwiseDir ) ) {
543
+ await this . writeBookIdToFrontmatter ( file , this . settings . booksIDsMap [ file . path ] ) ;
544
+ }
545
+ } ) ;
546
+
466
547
if ( this . settings . isSyncing ) {
467
548
if ( this . settings . currentSyncStatusID ) {
468
549
await this . getExportStatus ( ) ;
@@ -617,6 +698,27 @@ export default class ReadwisePlugin extends Plugin {
617
698
await this . saveSettings ( ) ;
618
699
return true ;
619
700
}
701
+
702
+ async writeBookIdToFrontmatter ( file : TFile , bookId : string ) {
703
+ console . log ( 'Readwise Official plugin: checking file for frontmatter' , file . path ) ;
704
+
705
+ if ( ! this . settings . frontmatterBookIdKey ) return ;
706
+
707
+ const cache = this . app . metadataCache . getFileCache ( file ) ;
708
+ if ( ! cache ) return ;
709
+
710
+ const frontmatter = cache . frontmatter ;
711
+ if ( ! frontmatter ) return ;
712
+
713
+ // don't overwrite existing book ID in frontmatter
714
+ const existingBookId = frontmatter [ this . settings . frontmatterBookIdKey ] ;
715
+ if ( existingBookId ) return ;
716
+
717
+ await this . app . fileManager . processFrontMatter ( file , frontmatter => {
718
+ console . log ( `Readwise Official plugin: setting frontmatter key for "${ file . path } " to ${ bookId } ` ) ;
719
+ frontmatter [ this . settings . frontmatterBookIdKey ] = bookId ;
720
+ } ) ;
721
+ }
620
722
}
621
723
622
724
class ReadwiseSettingTab extends PluginSettingTab {
@@ -734,6 +836,17 @@ class ReadwiseSettingTab extends PluginSettingTab {
734
836
}
735
837
) ;
736
838
839
+ new Setting ( containerEl )
840
+ . setName ( 'Advanced settings' )
841
+ . setDesc ( 'Customize additional settings for the Readwise plugin' )
842
+ . addButton ( button => {
843
+ button
844
+ . setButtonText ( 'Open' )
845
+ . onClick ( ( ) => {
846
+ new AdvancedModal ( this . app , this . plugin ) . open ( ) ;
847
+ } ) ;
848
+ } ) ;
849
+
737
850
if ( this . plugin . settings . lastSyncFailed ) {
738
851
this . plugin . showInfoStatus ( containerEl . find ( ".rw-setting-sync .rw-info-container" ) . parentElement , "Last sync failed" , "rw-error" ) ;
739
852
}
0 commit comments