2020-05-16 04:02:52 +08:00

281 lines
6.0 KiB
TypeScript

import { EventEmitter } from 'events';
const domReady = require('domready');
import Flags from './flags';
import { designer } from './editor';
function enterFullscreen() {
const elem = document.documentElement;
if (elem.requestFullscreen) {
elem.requestFullscreen();
}
}
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
}
}
function isFullscreen() {
return document.fullscreen || false;
}
interface IStyleResourceConfig {
media?: string;
type?: string;
content?: string;
}
class StyleResource {
config: IStyleResourceConfig;
styleElement: HTMLStyleElement;
mounted: boolean;
inited: boolean;
constructor(config: IStyleResourceConfig) {
this.config = config || {};
}
matchDevice(device: string) {
const media = this.config.media;
if (!media || media === 'ALL' || media === '*') {
return true;
}
return media.toUpperCase() === device.toUpperCase();
}
init() {
if (this.inited) {
return;
}
this.inited = true;
const { type, content } = this.config;
let styleElement: any;
if (type === 'URL') {
styleElement = document.createElement('link');
styleElement.href = content || '';
styleElement.rel = 'stylesheet';
} else {
styleElement = document.createElement('style');
styleElement.setAttribute('type', 'text/css');
if (styleElement.styleSheet) {
styleElement.styleSheet.cssText = content;
} else {
styleElement.appendChild(document.createTextNode(content || ''));
}
}
this.styleElement = styleElement;
}
apply() {
if (this.mounted) {
return;
}
this.init();
document.head.appendChild(this.styleElement);
this.mounted = true;
}
unmount() {
if (!this.mounted) {
return;
}
document.head.removeChild(this.styleElement);
this.mounted = false;
}
}
export class Viewport {
preview: boolean;
focused: boolean;
slateFixed: boolean;
emitter: EventEmitter;
device: string;
focusTarget: any;
cssResourceSet: StyleResource[];
constructor() {
this.preview = false;
this.emitter = new EventEmitter();
document.addEventListener('webkitfullscreenchange', () => {
this.emitter.emit('fullscreenchange', this.isFullscreen());
});
domReady(() => this.applyMediaCSS());
}
setFullscreen(flag: boolean) {
const fullscreen = this.isFullscreen();
if (fullscreen && !flag) {
exitFullscreen();
} else if (!fullscreen && flag) {
enterFullscreen();
}
}
toggleFullscreen() {
if (this.isFullscreen()) {
exitFullscreen();
} else {
enterFullscreen();
}
}
isFullscreen() {
return isFullscreen();
}
setFocus(flag: boolean) {
if (this.focused && !flag) {
this.focused = false;
Flags.remove('view-focused');
this.emitter.emit('focuschange', false);
} else if (!this.focused && flag) {
this.focused = true;
Flags.add('view-focused');
this.emitter.emit('focuschange', true);
}
}
setFocusTarget(focusTarget: any) {
this.focusTarget = focusTarget;
}
returnFocus() {
if (this.focusTarget) {
this.focusTarget.focus();
}
}
isFocus() {
return this.focused;
}
setPreview(flag: boolean) {
if (this.preview && !flag) {
this.preview = false;
Flags.setPreviewMode(false);
this.emitter.emit('preview', false);
this.changeViewport();
} else if (!this.preview && flag) {
this.preview = true;
Flags.setPreviewMode(true);
this.emitter.emit('preview', true);
this.changeViewport();
}
}
togglePreview() {
if (this.isPreview()) {
this.setPreview(false);
} else {
this.setPreview(true);
}
}
isPreview() {
return this.preview;
}
setDevice(device = 'pc') {
if (this.getDevice() !== device) {
this.device = device;
designer.currentDocument?.simulator?.set('device', device === 'mobile' ? 'mobile' : 'default');
// Flags.setSimulator(device);
// this.applyMediaCSS();
this.emitter.emit('devicechange', device);
this.changeViewport();
}
}
getDevice() {
return this.device || 'pc';
}
changeViewport() {
this.emitter.emit('viewportchange', this.getViewport());
}
getViewport() {
return `${this.isPreview() ? 'preview' : 'design'}-${this.getDevice()}`;
}
applyMediaCSS() {
if (!document.head || !this.cssResourceSet) {
return;
}
const device = this.getDevice();
this.cssResourceSet.forEach((item) => {
if (item.matchDevice(device)) {
item.apply();
} else {
item.unmount();
}
});
}
setGlobalCSS(resourceSet: IStyleResourceConfig[]) {
if (this.cssResourceSet) {
this.cssResourceSet.forEach((item) => {
item.unmount();
});
}
this.cssResourceSet = resourceSet.map((item: IStyleResourceConfig) => new StyleResource(item)).reverse();
this.applyMediaCSS();
}
setWithShell(shell: string) {
// Flags.setWithShell(shell);
}
onFullscreenChange(func: () => any) {
this.emitter.on('fullscreenchange', func);
return () => {
this.emitter.removeListener('fullscreenchange', func);
};
}
onPreview(func: () => any) {
this.emitter.on('preview', func);
return () => {
this.emitter.removeListener('preview', func);
};
}
onDeviceChange(func: () => any) {
this.emitter.on('devicechange', func);
return () => {
this.emitter.removeListener('devicechange', func);
};
}
onSlateFixedChange(func: (flag: boolean) => any) {
this.emitter.on('slatefixed', func);
return () => {
this.emitter.removeListener('slatefixed', func);
};
}
onViewportChange(func: () => any) {
this.emitter.on('viewportchange', func);
return () => {
this.emitter.removeListener('viewportchange', func);
};
}
onFocusChange(func: (flag: boolean) => any) {
this.emitter.on('focuschange', func);
return () => {
this.emitter.removeListener('focuschange', func);
};
}
}
export default new Viewport();