@@ -2638,10 +2638,30 @@ def all_annotation_types(self):
26382638 def all_annotation_styles (self ):
26392639 all_styles = [{'kind' : 'color' , 'which' : style } for style in builtin_colors_light .keys ()] + \
26402640 [{'kind' : 'decoration' , 'which' : style } for style in builtin_decorations .keys ()]
2641- # In the future, we could merge in custom styles from the DB.
2642- # Under the current schema, this would require scanning all annotations,
2643- # so it's excluded for performance at this time.
2644- return {style ['which' ]: style for style in all_styles }
2641+ ans = {style ['which' ]: style for style in all_styles }
2642+ # Merge in custom highlight styles found in the database. Custom
2643+ # styles are stored as JSON inside the annot_data column with
2644+ # 'type': 'custom' and a 'friendly_name' key. We scan the DB to
2645+ # discover them, since they are not part of the built-in set.
2646+ try :
2647+ for (raw_annot_data ,) in self .execute (
2648+ "SELECT annot_data FROM annotations"
2649+ " WHERE json_extract(annot_data, '$.style.type') = 'custom'"
2650+ " AND json_extract(annot_data, '$.removed') IS NULL"
2651+ ):
2652+ try :
2653+ style = json .loads (raw_annot_data ).get ('style' )
2654+ except Exception :
2655+ continue
2656+ if style is not None and isinstance (style , dict ):
2657+ name = style .get ('friendly_name' ) or style .get ('which' )
2658+ if name and name not in ans :
2659+ ans [name ] = style
2660+ except Exception :
2661+ # Best-effort: if the query fails (e.g. schema mismatch) just
2662+ # return the built-in styles.
2663+ pass
2664+ return ans
26452665
26462666 def set_annotations_for_book (self , book_id , fmt , annots_list , user_type = 'local' , user = 'viewer' ):
26472667 try :
0 commit comments