Files
flipper/desktop/plugins/public/navigation/plugin.tsx
Andrey Goncharov 6c74f2dd18 Set device features on device initialization
Summary:
1. Identify if device supports screenshots/screen recording when it is created.
2. Disable screen recording/screenshot buttons when they are not supported

Reviewed By: passy

Differential Revision: D34611133

fbshipit-source-id: 82ad2d67e4af482d9becf7995187667b5d99bc36
2022-03-04 02:00:23 -08:00

195 lines
5.4 KiB
TypeScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/
import {RequiredParametersDialog} from './components';
import {
removeBookmarkFromDB,
readBookmarksFromDB,
writeBookmarkToDB,
} from './util/indexedDB';
import {} from './util/autoCompleteProvider';
import {getAppMatchPatterns} from './util/appMatchPatterns';
import {getRequiredParameters, filterOptionalParameters} from './util/uri';
import {
Bookmark,
NavigationEvent,
AppMatchPattern,
URI,
RawNavigationEvent,
} from './types';
import React from 'react';
import {PluginClient, createState, renderReactRoot} from 'flipper-plugin';
export type State = {
shouldShowSaveBookmarkDialog: boolean;
shouldShowURIErrorDialog: boolean;
saveBookmarkURI: URI | null;
requiredParameters: Array<string>;
};
type Events = {
nav_event: RawNavigationEvent;
};
type Methods = {
navigate_to(params: {url: string}): Promise<void>;
};
export type NavigationPlugin = ReturnType<typeof plugin>;
export function plugin(client: PluginClient<Events, Methods>) {
const bookmarks = createState(new Map<URI, Bookmark>(), {
persist: 'bookmarks',
});
const navigationEvents = createState<NavigationEvent[]>([], {
persist: 'navigationEvents',
});
const appMatchPatterns = createState<AppMatchPattern[]>([], {
persist: 'appMatchPatterns',
});
const currentURI = createState('');
const shouldShowSaveBookmarkDialog = createState(false);
const saveBookmarkURI = createState<null | string>(null);
client.onMessage('nav_event', async (payload) => {
const navigationEvent: NavigationEvent = {
uri: payload.uri === undefined ? null : decodeURIComponent(payload.uri),
date: payload.date ? new Date(payload.date) : new Date(),
className: payload.class === undefined ? null : payload.class,
screenshot: null,
};
if (navigationEvent.uri) currentURI.set(navigationEvent.uri);
navigationEvents.update((draft) => {
draft.unshift(navigationEvent);
});
const screenshot = await client.device.screenshot();
if (!screenshot) {
console.warn(
'[navigation] Could not retrieve valid screenshot from the device.',
);
return;
}
const blobURL = URL.createObjectURL(new Blob([screenshot.buffer]));
// this process is async, make sure we update the correct one..
const navigationEventIndex = navigationEvents
.get()
.indexOf(navigationEvent);
if (navigationEventIndex !== -1) {
navigationEvents.update((draft) => {
draft[navigationEventIndex].screenshot = blobURL;
});
}
});
getAppMatchPatterns(client.appId, client.device)
.then((patterns) => {
appMatchPatterns.set(patterns);
})
.catch((e) => {
console.error('[Navigation] Failed to find appMatchPatterns', e);
});
readBookmarksFromDB()
.then((bookmarksData) => {
bookmarks.set(bookmarksData);
})
.catch((e) => console.error('[navigation] readBookmarksFromDB failed:', e));
function navigateTo(query: string) {
const filteredQuery = filterOptionalParameters(query);
currentURI.set(filteredQuery);
const params = getRequiredParameters(filteredQuery);
if (params.length === 0) {
if (client.appName === 'Facebook' && client.device.os === 'iOS') {
// use custom navigate_to event for Wilde
client.send('navigate_to', {
url: filterOptionalParameters(filteredQuery),
});
} else {
client.device.navigateToLocation(
filterOptionalParameters(filteredQuery),
);
}
} else {
renderReactRoot((unmount) => (
<RequiredParametersDialog
onHide={unmount}
uri={filteredQuery}
requiredParameters={params}
onSubmit={navigateTo}
/>
));
}
}
function onFavorite(uri: string) {
shouldShowSaveBookmarkDialog.set(true);
saveBookmarkURI.set(uri);
}
function addBookmark(bookmark: Bookmark) {
const newBookmark = {
uri: bookmark.uri,
commonName: bookmark.commonName,
};
bookmarks.update((draft) => {
draft.set(newBookmark.uri, newBookmark);
});
writeBookmarkToDB(newBookmark);
}
function removeBookmark(uri: string) {
bookmarks.update((draft) => {
draft.delete(uri);
});
removeBookmarkFromDB(uri);
}
return {
navigateTo,
onFavorite,
addBookmark,
removeBookmark,
bookmarks,
saveBookmarkURI,
shouldShowSaveBookmarkDialog,
appMatchPatterns,
navigationEvents,
currentURI,
getAutoCompleteAppMatchPatterns(
query: string,
bookmarks: Map<string, Bookmark>,
appMatchPatterns: AppMatchPattern[],
limit: number,
): AppMatchPattern[] {
const q = query.toLowerCase();
const results: AppMatchPattern[] = [];
for (const item of appMatchPatterns) {
if (
!bookmarks.has(item.pattern) &&
(item.className.toLowerCase().includes(q) ||
item.pattern.toLowerCase().includes(q))
) {
results.push(item);
if (--limit < 1) break;
}
}
return results;
},
};
}
/* @scarf-info: do not remove, more info: https://fburl.com/scarf */
/* @scarf-generated: flipper-plugin index.js.template 0bfa32e5-fb15-4705-81f8-86260a1f3f8e */