Add a new preference, viewerCssTheme, to allow forcing the use of the light/dark viewer CSS themes (issue 12290)
				
					
				
			While this does work pretty well in my quick testing, it's *very much* a hack since as far as I can tell there's no support in the CSS specification for using e.g. a CSS variable to override a `@media (prefers-color-scheme: dark) {...}` block.
The solution implemented here is thus to *edit* the viewer CSS, by either removing the entire `@media ...` block in light-mode or by ensuring that its rules become *unconditionally* applied in dark-mode.
To simplify the overall implementation, since all of this does seem like somewhat of an edge-case, the `viewerCssTheme` preference will *only* be read during viewer initialization. (Similar to many other existing preferences, a reload is thus required when changing it.)
			
			
This commit is contained in:
		
							parent
							
								
									f39d87bff1
								
							
						
					
					
						commit
						40a4d53fb3
					
				@ -198,6 +198,15 @@
 | 
			
		||||
        2
 | 
			
		||||
      ],
 | 
			
		||||
      "default": -1
 | 
			
		||||
    },
 | 
			
		||||
    "viewerCssTheme": {
 | 
			
		||||
      "type": "integer",
 | 
			
		||||
      "enum": [
 | 
			
		||||
        0,
 | 
			
		||||
        1,
 | 
			
		||||
        2
 | 
			
		||||
      ],
 | 
			
		||||
      "default": 0
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										47
									
								
								web/app.js
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								web/app.js
									
									
									
									
									
								
							@ -90,6 +90,12 @@ const ViewOnLoad = {
 | 
			
		||||
  INITIAL: 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const ViewerCssTheme = {
 | 
			
		||||
  AUTOMATIC: 0, // Default value.
 | 
			
		||||
  LIGHT: 1,
 | 
			
		||||
  DARK: 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Keep these in sync with mozilla-central's Histograms.json.
 | 
			
		||||
const KNOWN_VERSIONS = [
 | 
			
		||||
  "1.0",
 | 
			
		||||
@ -256,6 +262,7 @@ const PDFViewerApplication = {
 | 
			
		||||
 | 
			
		||||
    await this._readPreferences();
 | 
			
		||||
    await this._parseHashParameters();
 | 
			
		||||
    this._forceCssTheme();
 | 
			
		||||
    await this._initializeL10n();
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
@ -396,6 +403,46 @@ const PDFViewerApplication = {
 | 
			
		||||
    document.getElementsByTagName("html")[0].dir = dir;
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @private
 | 
			
		||||
   */
 | 
			
		||||
  _forceCssTheme() {
 | 
			
		||||
    const cssTheme = AppOptions.get("viewerCssTheme");
 | 
			
		||||
    if (
 | 
			
		||||
      cssTheme === ViewerCssTheme.AUTOMATIC ||
 | 
			
		||||
      !Object.values(ViewerCssTheme).includes(cssTheme)
 | 
			
		||||
    ) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
      const styleSheet = document.styleSheets[0];
 | 
			
		||||
      const cssRules = styleSheet?.cssRules || [];
 | 
			
		||||
      for (let i = 0, ii = cssRules.length; i < ii; i++) {
 | 
			
		||||
        const rule = cssRules[i];
 | 
			
		||||
        if (
 | 
			
		||||
          rule instanceof CSSMediaRule &&
 | 
			
		||||
          rule.media?.[0] === "(prefers-color-scheme: dark)"
 | 
			
		||||
        ) {
 | 
			
		||||
          if (cssTheme === ViewerCssTheme.LIGHT) {
 | 
			
		||||
            styleSheet.deleteRule(i);
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          // cssTheme === ViewerCssTheme.DARK
 | 
			
		||||
          const darkRules = /^@media \(prefers-color-scheme: dark\) {\n\s*([\w\s-.,:;/\\{}()]+)\n}$/.exec(
 | 
			
		||||
            rule.cssText
 | 
			
		||||
          );
 | 
			
		||||
          if (darkRules?.[1]) {
 | 
			
		||||
            styleSheet.deleteRule(i);
 | 
			
		||||
            styleSheet.insertRule(darkRules[1], i);
 | 
			
		||||
          }
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } catch (reason) {
 | 
			
		||||
      console.error(`_forceCssTheme: "${reason?.message}".`);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @private
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
@ -154,6 +154,11 @@ const defaultOptions = {
 | 
			
		||||
    value: false,
 | 
			
		||||
    kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
 | 
			
		||||
  },
 | 
			
		||||
  viewerCssTheme: {
 | 
			
		||||
    /** @type {number} */
 | 
			
		||||
    value: 0,
 | 
			
		||||
    kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
 | 
			
		||||
  },
 | 
			
		||||
  viewOnLoad: {
 | 
			
		||||
    /** @type {boolean} */
 | 
			
		||||
    value: 0,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user