environment manager (#1784)
This PR extracts the environment manager from #1778. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] Move environment flags to environment manager
This commit is contained in:
parent
79fae186e4
commit
c478d75117
8 changed files with 69 additions and 54 deletions
|
@ -630,6 +630,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
// (undocumented)
|
||||
duplicateShapes(ids: TLShapeId[], offset?: VecLike): this;
|
||||
get editingShapeId(): null | TLShapeId;
|
||||
readonly environment: EnvironmentManager;
|
||||
get erasingShapeIds(): TLShapeId[];
|
||||
get erasingShapeIdsSet(): Set<TLShapeId>;
|
||||
// @internal (undocumented)
|
||||
|
@ -805,12 +806,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
isAncestorSelected(id: TLShapeId): boolean;
|
||||
// (undocumented)
|
||||
isAncestorSelected(shape: TLShape): boolean;
|
||||
readonly isAndroid: boolean;
|
||||
readonly isChromeForIos: boolean;
|
||||
readonly isFirefox: boolean;
|
||||
isIn(path: string): boolean;
|
||||
isInAny(...paths: string[]): boolean;
|
||||
readonly isIos: boolean;
|
||||
get isMenuOpen(): boolean;
|
||||
isPointInShape(shape: TLShape, point: VecLike, opts?: {
|
||||
margin?: number;
|
||||
|
@ -821,7 +818,6 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
margin?: number;
|
||||
hitInside?: boolean;
|
||||
}): boolean;
|
||||
readonly isSafari: boolean;
|
||||
isShapeInPage(shape: TLShape, pageId?: TLPageId): boolean;
|
||||
// (undocumented)
|
||||
isShapeInPage(shapeId: TLShapeId, pageId?: TLPageId): boolean;
|
||||
|
|
|
@ -103,6 +103,7 @@ import { arrowBindingsIndex } from './derivations/arrowBindingsIndex'
|
|||
import { parentsToChildren } from './derivations/parentsToChildren'
|
||||
import { deriveShapeIdsInCurrentPage } from './derivations/shapeIdsInCurrentPage'
|
||||
import { ClickManager } from './managers/ClickManager'
|
||||
import { EnvironmentManager } from './managers/EnvironmentManager'
|
||||
import { HistoryManager } from './managers/HistoryManager'
|
||||
import { SnapManager } from './managers/SnapManager'
|
||||
import { TextManager } from './managers/TextManager'
|
||||
|
@ -239,19 +240,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
this.root.children![Tool.id] = new Tool(this, this.root)
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && 'navigator' in window) {
|
||||
this.isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
|
||||
this.isIos = !!navigator.userAgent.match(/iPad/i) || !!navigator.userAgent.match(/iPhone/i)
|
||||
this.isChromeForIos = /crios.*safari/i.test(navigator.userAgent)
|
||||
this.isFirefox = /firefox/i.test(navigator.userAgent)
|
||||
this.isAndroid = /android/i.test(navigator.userAgent)
|
||||
} else {
|
||||
this.isSafari = false
|
||||
this.isIos = false
|
||||
this.isChromeForIos = false
|
||||
this.isFirefox = false
|
||||
this.isAndroid = false
|
||||
}
|
||||
this.environment = new EnvironmentManager(this)
|
||||
|
||||
this.store.onBeforeDelete = (record) => {
|
||||
if (record.typeName === 'shape') {
|
||||
|
@ -412,39 +401,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
readonly textMeasure: TextManager
|
||||
|
||||
/**
|
||||
* Whether the editor is running in Safari.
|
||||
* A manager for the editor's environment.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isSafari: boolean
|
||||
|
||||
/**
|
||||
* Whether the editor is running on iOS.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isIos: boolean
|
||||
|
||||
/**
|
||||
* Whether the editor is running on iOS.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isChromeForIos: boolean
|
||||
|
||||
/**
|
||||
* Whether the editor is running on Firefox.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isFirefox: boolean
|
||||
|
||||
/**
|
||||
* Whether the editor is running on Android.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isAndroid: boolean
|
||||
readonly environment: EnvironmentManager
|
||||
|
||||
/**
|
||||
* The current HTML element containing the editor.
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import { Editor } from '../Editor'
|
||||
|
||||
export class EnvironmentManager {
|
||||
constructor(public editor: Editor) {
|
||||
if (typeof window !== 'undefined' && 'navigator' in window) {
|
||||
this.isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
|
||||
this.isIos = !!navigator.userAgent.match(/iPad/i) || !!navigator.userAgent.match(/iPhone/i)
|
||||
this.isChromeForIos = /crios.*safari/i.test(navigator.userAgent)
|
||||
this.isFirefox = /firefox/i.test(navigator.userAgent)
|
||||
this.isAndroid = /android/i.test(navigator.userAgent)
|
||||
} else {
|
||||
this.isSafari = false
|
||||
this.isIos = false
|
||||
this.isChromeForIos = false
|
||||
this.isFirefox = false
|
||||
this.isAndroid = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the editor is running in Safari.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isSafari: boolean
|
||||
|
||||
/**
|
||||
* Whether the editor is running on iOS.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isIos: boolean
|
||||
|
||||
/**
|
||||
* Whether the editor is running on iOS.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isChromeForIos: boolean
|
||||
|
||||
/**
|
||||
* Whether the editor is running on Firefox.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isFirefox: boolean
|
||||
|
||||
/**
|
||||
* Whether the editor is running on Android.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
readonly isAndroid: boolean
|
||||
}
|
|
@ -7,7 +7,11 @@ export function useCoarsePointer() {
|
|||
// This is a workaround for a Firefox bug where we don't correctly
|
||||
// detect coarse VS fine pointer. For now, let's assume that you have a fine
|
||||
// pointer if you're on Firefox on desktop.
|
||||
if (editor.isFirefox && !editor.isAndroid && !editor.isIos) {
|
||||
if (
|
||||
editor.environment.isFirefox &&
|
||||
!editor.environment.isAndroid &&
|
||||
!editor.environment.isIos
|
||||
) {
|
||||
editor.updateInstanceState({ isCoarsePointer: false })
|
||||
return
|
||||
}
|
||||
|
|
|
@ -495,7 +495,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
|
|||
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const changeIndex = React.useMemo<number>(() => {
|
||||
return this.editor.isSafari ? (globalRenderIndex += 1) : 0
|
||||
return this.editor.environment.isSafari ? (globalRenderIndex += 1) : 0
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [shape])
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ function PatternFillDefForCanvas() {
|
|||
const { defs, isReady } = usePattern()
|
||||
|
||||
useEffect(() => {
|
||||
if (isReady && editor.isSafari) {
|
||||
if (isReady && editor.environment.isSafari) {
|
||||
const htmlLayer = findHtmlLayerParent(containerRef.current!)
|
||||
if (htmlLayer) {
|
||||
// Wait for `patternContext` to be picked up
|
||||
|
|
|
@ -379,7 +379,7 @@ export const PageMenu = function PageMenu() {
|
|||
item={page}
|
||||
listSize={pages.length}
|
||||
onRename={() => {
|
||||
if (editor.isIos) {
|
||||
if (editor.environment.isIos) {
|
||||
const name = window.prompt('Rename page', page.name)
|
||||
if (name && name !== page.name) {
|
||||
editor.renamePage(page.id, name)
|
||||
|
|
|
@ -156,10 +156,10 @@ export function usePrint() {
|
|||
}
|
||||
|
||||
function triggerPrint() {
|
||||
if (editor.isChromeForIos) {
|
||||
if (editor.environment.isChromeForIos) {
|
||||
beforePrintHandler()
|
||||
window.print()
|
||||
} else if (editor.isSafari) {
|
||||
} else if (editor.environment.isSafari) {
|
||||
beforePrintHandler()
|
||||
document.execCommand('print', false)
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue