Skip to content
This repository has been archived by the owner on Nov 22, 2024. It is now read-only.

Commit

Permalink
Open file import
Browse files Browse the repository at this point in the history
Summary: This change only adds the PWA as capable of handling files with the ".flipper" extension.

Reviewed By: aigoncharov

Differential Revision: D48353437

fbshipit-source-id: fd78942ac4dffb7d26d5ca5be826290018465b93
  • Loading branch information
lblasa authored and facebook-github-bot committed Aug 17, 2023
1 parent 9728155 commit ce13ee4
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 106 deletions.
4 changes: 2 additions & 2 deletions desktop/flipper-frontend-core/src/RenderHost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ interface NotificationConstructorOptions {
// Events that are emitted from the main.ts ovr the IPC process bridge in Electron
type MainProcessEvents = {
'flipper-protocol-handler': [query: string];
'open-flipper-file': [url: string];
'open-flipper-file': [name: string, data: string];
notificationEvent: [
eventName: NotificationEvents,
pluginNotification: PluginNotification,
Expand All @@ -88,7 +88,7 @@ type ChildProcessEvents = {
},
];
getLaunchTime: [];
componentDidMount: [];
storeRehydrated: [];
};

/**
Expand Down
72 changes: 72 additions & 0 deletions desktop/flipper-ui-browser/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,15 @@ async function start() {
const flipperServerConfig = await flipperServer.exec('get-config');

initializeRenderHost(flipperServer, flipperServerConfig);
initializePWA();

// By turning this in a require, we force the JS that the body of this module (init) has completed (initializeElectron),
// before starting the rest of the Flipper process.
// This prevent issues where the render host is referred at module initialisation level,
// but not set yet, which might happen when using normal imports.
// TODO: remove
window.flipperShowError?.('Connected to Flipper Server successfully');

// @ts-ignore
// eslint-disable-next-line import/no-commonjs
require('flipper-ui-core').startFlipperDesktop(flipperServer);
Expand All @@ -89,6 +91,76 @@ start().catch((e) => {
window.flipperShowError?.('Failed to start flipper-ui-browser: ' + e);
});

async function initializePWA() {
console.log('[PWA] Initialization');

let cachedFile: {name: string; data: string} | undefined;
let rehydrated = false;
const openFileIfAny = () => {
if (!cachedFile || !rehydrated) {
return;
}
window.dispatchEvent(
new CustomEvent('open-flipper-file', {
detail: [cachedFile.name, cachedFile.data],
}),
);
cachedFile = undefined;
};

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/service-worker.js')
.then(() => {
console.log('[PWA] Service Worker has been registered');
})
.catch((e) => {
console.error('[PWA] failed to register Service Worker', e);
});
}

if ('launchQueue' in window) {
console.log('[PWA] File Handling API is supported');

// @ts-ignore
window.launchQueue.setConsumer(async (launchParams) => {
if (!launchParams || !launchParams.files) {
return;
}
console.log('[PWA] Attempt to to open a file');
for (const file of launchParams.files) {
const blob = await file.getFile();
blob.handle = file;

const data = await blob.text();
const name = file.name;

cachedFile = {name, data};

openFileIfAny();
}
});
} else {
console.warn('[PWA] File Handling API is not supported');
}

console.log('[PWA] Add before install prompt listener');
window.addEventListener('beforeinstallprompt', (e) => {
// Prevent Chrome 67 and earlier from automatically showing the prompt.
e.preventDefault();
// Stash the event so it can be triggered later.
// @ts-ignore
global.PWAppInstallationEvent = e;
console.log('[PWA] Installation event has been captured');
});

window.addEventListener('storeRehydrated', () => {
console.info('[PWA] Store is rehydrated');
rehydrated = true;
openFileIfAny();
});
}

// getLogger() is not yet created when the electron app starts.
// we can't create it here yet, as the real logger is wired up to
// the redux store and the rest of the world. So we create a delegating logger
Expand Down
10 changes: 6 additions & 4 deletions desktop/flipper-ui-browser/src/initializeRenderHost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,13 @@ export function initializeRenderHost(
hasFocus() {
return document.hasFocus();
},
onIpcEvent(_event) {
// no-op
onIpcEvent(event, cb) {
window.addEventListener(event as string, (ev) => {
cb(...((ev as CustomEvent).detail as any));
});
},
sendIpcEvent(_event, ..._args: any[]) {
// no-op
sendIpcEvent(event, ...args: any[]) {
window.dispatchEvent(new CustomEvent(event, {detail: args}));
},
shouldUseDarkColors() {
return !!(
Expand Down
6 changes: 3 additions & 3 deletions desktop/flipper-ui-core/src/dispatcher/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import {Store} from '../reducers/index';
import {Logger} from 'flipper-common';
import {
importFileToStore,
importDataToStore,
IMPORT_FLIPPER_TRACE_EVENT,
} from '../utils/exportData';
import {tryCatchReportPlatformFailures} from 'flipper-common';
Expand Down Expand Up @@ -67,9 +67,9 @@ export default (store: Store, logger: Logger) => {
});
});

renderHost.onIpcEvent('open-flipper-file', (url: string) => {
renderHost.onIpcEvent('open-flipper-file', (name: string, data: string) => {
tryCatchReportPlatformFailures(() => {
return importFileToStore(url, store);
return importDataToStore(name, data, store);
}, `${IMPORT_FLIPPER_TRACE_EVENT}:Deeplink`);
});
};
16 changes: 10 additions & 6 deletions desktop/flipper-ui-core/src/dispatcher/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ import {Store} from '../reducers/index';
import {Dispatcher} from './types';
import {notNull} from '../utils/typeUtils';

export default function (store: Store, logger: Logger): () => Promise<void> {
export default async function (
store: Store,
logger: Logger,
): Promise<() => Promise<void>> {
// This only runs in development as when the reload
// kicks in it doesn't unregister the shortcuts
const dispatchers: Array<Dispatcher> = [
Expand All @@ -43,10 +46,11 @@ export default function (store: Store, logger: Logger): () => Promise<void> {
pluginChangeListener,
pluginsSourceUpdateListener,
].filter(notNull);
const globalCleanup = dispatchers
.map((dispatcher) => dispatcher(store, logger))
.filter(Boolean);
return () => {
return Promise.all(globalCleanup).then(() => {});
const globalCleanup = await Promise.all(
dispatchers.map((dispatcher) => dispatcher(store, logger)).filter(Boolean),
);

return async () => {
await Promise.all(globalCleanup);
};
}
1 change: 0 additions & 1 deletion desktop/flipper-ui-core/src/sandy-chrome/SandyApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,5 +196,4 @@ function registerStartupTime(logger: Logger) {
});

renderHost.sendIpcEvent('getLaunchTime');
renderHost.sendIpcEvent('componentDidMount');
}
23 changes: 12 additions & 11 deletions desktop/flipper-ui-core/src/startFlipperDesktop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,10 @@ function init(flipperServer: FlipperServer) {
loadTheme(settings.darkMode);

// rehydrate app state before exposing init
const persistor = persistStore(store, undefined, () => {
const persistor = persistStore(store, undefined, async () => {
// Make sure process state is set before dispatchers run
dispatcher(store, logger);
await dispatcher(store, logger);
getRenderHostInstance().sendIpcEvent('storeRehydrated');
});

setPersistor(persistor);
Expand All @@ -168,17 +169,17 @@ function init(flipperServer: FlipperServer) {

connectFlipperServerToStore(flipperServer, store, logger);

enableConsoleHook();
enableConnectivityHook(flipperServer);

// TODO T116224873: Return the following code back instead of ReactDOM.react when the following issue is fixed: https://github.com/react-component/trigger/issues/288
// const root = createRoot(document.getElementById('root')!);
// root.render(<AppFrame logger={logger} persistor={persistor} />);

ReactDOM.render(
<AppFrame logger={logger} persistor={persistor} />,
document.getElementById('root')!,
);

enableConsoleHook();
enableConnectivityHook(flipperServer);
const root = document.getElementById('root');
if (root) {
ReactDOM.render(<AppFrame logger={logger} persistor={persistor} />, root);
}

const launcherMessage =
getRenderHostInstance().serverConfig.processConfig.launcherMsg;
Expand All @@ -193,8 +194,8 @@ function init(flipperServer: FlipperServer) {
}
}

export async function startFlipperDesktop(flipperServer: FlipperServer) {
getRenderHostInstance(); // renderHost instance should be set at this point!
export function startFlipperDesktop(flipperServer: FlipperServer) {
getRenderHostInstance();
init(flipperServer);
}

Expand Down
5 changes: 3 additions & 2 deletions desktop/flipper-ui-core/src/utils/exportData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {TestIdler} from './Idler';
import {processMessageQueue} from './messageQueue';
import {getPluginTitle} from './pluginUtils';
import {capture} from './screenshot';
import {Dialog, getFlipperLib, Idler, path} from 'flipper-plugin';
import {Dialog, getFlipperLib, Idler} from 'flipper-plugin';
import {ClientQuery} from 'flipper-common';
import ShareSheetExportUrl from '../chrome/ShareSheetExportUrl';
import ShareSheetExportFile from '../chrome/ShareSheetExportFile';
Expand All @@ -43,6 +43,7 @@ import {safeFilename} from './safeFilename';
import {getExportablePlugins} from '../selectors/connections';
import {notification} from 'antd';
import openSupportRequestForm from '../fb-stubs/openSupportRequestForm';
import {getStore} from '../store';

export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace';
export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace';
Expand Down Expand Up @@ -526,7 +527,7 @@ export const exportStoreToFile = (
export async function importDataToStore(
source: string,
data: string,
store: Store,
store: Store = getStore(),
) {
getLogger().track('usage', IMPORT_FLIPPER_TRACE_EVENT);
const json: ExportType = JSON.parse(data);
Expand Down
19 changes: 0 additions & 19 deletions desktop/static/index.web.dev.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,6 @@
document.body.appendChild(script);
}

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/service-worker.js')
.then(() => {
console.log('Flipper Service Worker has been registered');
})
.catch((e) => {
console.error('Flipper failed to register Service Worker', e);
});
}

window.addEventListener('beforeinstallprompt', (e) => {
console.log('Flipper PWA before install prompt with event', e);
// Prevent Chrome 67 and earlier from automatically showing the prompt.
e.preventDefault();
// Stash the event so it can be triggered later.
global.PWAppInstallationEvent = e;
});

init();
})();
</script>
Expand Down
21 changes: 1 addition & 20 deletions desktop/static/index.web.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
</div>
</div>

<div class="__infinity-dev-box __infinity-dev-box-error" hidden />
<div class="__infinity-dev-box __infinity-dev-box-error" hidden></div>
<script>
(function () {
// FIXME: needed to make Metro work
Expand Down Expand Up @@ -114,25 +114,6 @@

document.body.appendChild(script);
}

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/service-worker.js')
.then(() => {
console.log('Flipper Service Worker has been registered');
})
.catch((e) => {
console.error('Flipper failed to register Service Worker', e);
});
}

window.addEventListener('beforeinstallprompt', (e) => {
// Prevent Chrome 67 and earlier from automatically showing the prompt.
e.preventDefault();
// Stash the event so it can be triggered later.
global.PWAppInstallationEvent = e;
});

init();
})();
</script>
Expand Down
Loading

0 comments on commit ce13ee4

Please sign in to comment.