mirror of
https://github.com/standardnotes/app.git
synced 2026-01-11 19:56:41 +00:00
fix: Fix native themes not working on external editors (#2957) [skip e2e]
This commit is contained in:
parent
cffb516b6e
commit
60e92c7035
4 changed files with 66 additions and 1 deletions
|
|
@ -38,6 +38,9 @@ import {
|
|||
DocumentDirectoryPath,
|
||||
DownloadDirectoryPath,
|
||||
exists,
|
||||
MainBundlePath,
|
||||
readFile,
|
||||
readFileAssets,
|
||||
unlink,
|
||||
writeFile,
|
||||
} from 'react-native-fs'
|
||||
|
|
@ -508,6 +511,15 @@ export class MobileDevice implements MobileDeviceInterface {
|
|||
}
|
||||
}
|
||||
|
||||
async getNativeThemeCSS(identifier: string): Promise<string | undefined> {
|
||||
let path = `Web.bundle/src/web-src/components/assets/${identifier}/index.css`
|
||||
if (Platform.OS === 'ios') {
|
||||
path = `${MainBundlePath}/${path}`
|
||||
}
|
||||
const content = Platform.OS === 'android' ? readFileAssets(path) : readFile(path)
|
||||
return content
|
||||
}
|
||||
|
||||
async previewFile(base64: string, filename: string): Promise<boolean> {
|
||||
const tempLocation = await this.downloadBase64AsFile(base64, filename, true)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export interface MobileDeviceInterface extends DeviceInterface {
|
|||
handleThemeSchemeChange(isDark: boolean, bgColor: string): void
|
||||
shareBase64AsFile(base64: string, filename: string): Promise<void>
|
||||
downloadBase64AsFile(base64: string, filename: string, saveInTempLocation?: boolean): Promise<string | undefined>
|
||||
getNativeThemeCSS(identifier: string): Promise<string | undefined>
|
||||
previewFile(base64: string, filename: string): Promise<boolean>
|
||||
exitApp(confirm?: boolean): void
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import {
|
|||
NativeFeatureIdentifier,
|
||||
GetDeprecatedEditors,
|
||||
} from '@standardnotes/features'
|
||||
import { Copy, removeFromArray, sleep, isNotUndefined, LoggerInterface } from '@standardnotes/utils'
|
||||
import { Copy, removeFromArray, sleep, isNotUndefined, LoggerInterface, blobToBase64 } from '@standardnotes/utils'
|
||||
import { ComponentViewer } from '@Lib/Services/ComponentManager/ComponentViewer'
|
||||
import {
|
||||
AbstractService,
|
||||
|
|
@ -90,6 +90,8 @@ export class ComponentManager
|
|||
this.items,
|
||||
)
|
||||
|
||||
private nativeThemesAsBase64: Record<string, string> = {}
|
||||
|
||||
constructor(
|
||||
private items: ItemManagerInterface,
|
||||
private mutator: MutatorClientInterface,
|
||||
|
|
@ -109,6 +111,7 @@ export class ComponentManager
|
|||
this.addSyncedComponentItemObserver()
|
||||
this.registerMobileNativeComponentUrls()
|
||||
this.registerDeprecatedEditorUrlsForAndroid()
|
||||
void this.fetchNativeThemesOnMobile()
|
||||
|
||||
this.eventDisposers.push(
|
||||
preferences.addEventObserver((event) => {
|
||||
|
|
@ -295,6 +298,29 @@ export class ComponentManager
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the native themes' CSS and stores them as `data:text/css;base64,...` URLs.
|
||||
*/
|
||||
private async fetchNativeThemesOnMobile(): Promise<void> {
|
||||
if (!isMobileDevice(this.device)) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
for await (const theme of GetNativeThemes()) {
|
||||
const css = await this.device.getNativeThemeCSS(theme.identifier)
|
||||
if (css) {
|
||||
const blob = new Blob([css], { type: 'text/css' })
|
||||
const base64 = await blobToBase64(blob)
|
||||
this.nativeThemesAsBase64[theme.identifier] = base64
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
this.postActiveThemesToAllViewers()
|
||||
}
|
||||
}
|
||||
|
||||
private registerDeprecatedEditorUrlsForAndroid(): void {
|
||||
if (!isMobileDevice(this.device)) {
|
||||
return
|
||||
|
|
@ -367,7 +393,19 @@ export class ComponentManager
|
|||
public urlsForActiveThemes(): string[] {
|
||||
const themes = this.getActiveThemes()
|
||||
const urls = []
|
||||
const isMobile = isMobileDevice(this.device)
|
||||
for (const theme of themes) {
|
||||
if (isMobile && theme.isNativeFeature) {
|
||||
/**
|
||||
* Since native themes on mobile are stored in the app bundle and accessed as `file://` URLs,
|
||||
* external editors cannot access them. To solve this, we store base64 encoded versions of the themes and send those to the editor instead of a file URL.
|
||||
*/
|
||||
const base64 = this.nativeThemesAsBase64[theme.featureIdentifier]
|
||||
if (base64) {
|
||||
urls.push(base64)
|
||||
continue
|
||||
}
|
||||
}
|
||||
const url = this.urlForFeature(theme)
|
||||
if (url) {
|
||||
urls.push(url)
|
||||
|
|
|
|||
|
|
@ -699,3 +699,17 @@ export function spaceSeparatedStrings(...strings: string[]): string {
|
|||
export function pluralize(count: number, singular: string, plural: string): string {
|
||||
return count === 1 ? singular : plural
|
||||
}
|
||||
|
||||
export function blobToBase64(blob: Blob): Promise<string> {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.onloadend = () => {
|
||||
if (reader.result && typeof reader.result === 'string') {
|
||||
resolve(reader.result)
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
}
|
||||
reader.readAsDataURL(blob)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue