diff --git a/desktop/plugins/public/navigation/Component.tsx b/desktop/plugins/public/navigation/Component.tsx
new file mode 100644
index 000000000..347a18753
--- /dev/null
+++ b/desktop/plugins/public/navigation/Component.tsx
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) Facebook, Inc. and its 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 {
+ BookmarksSidebar,
+ SaveBookmarkDialog,
+ SearchBar,
+ Timeline,
+} from './components';
+import {
+ appMatchPatternsToAutoCompleteProvider,
+ bookmarksToAutoCompleteProvider,
+} from './util/autoCompleteProvider';
+import React, {useMemo} from 'react';
+import {useValue, usePlugin, Layout} from 'flipper-plugin';
+import {plugin} from './plugin';
+
+export function Component() {
+ const instance = usePlugin(plugin);
+ const bookmarks = useValue(instance.bookmarks);
+ const appMatchPatterns = useValue(instance.appMatchPatterns);
+ const saveBookmarkURI = useValue(instance.saveBookmarkURI);
+ const shouldShowSaveBookmarkDialog = useValue(
+ instance.shouldShowSaveBookmarkDialog,
+ );
+ const currentURI = useValue(instance.currentURI);
+ const navigationEvents = useValue(instance.navigationEvents);
+
+ const autoCompleteProviders = useMemo(
+ () => [
+ bookmarksToAutoCompleteProvider(bookmarks),
+ appMatchPatternsToAutoCompleteProvider(appMatchPatterns),
+ ],
+ [bookmarks, appMatchPatterns],
+ );
+ return (
+
+
+
+
+ {
+ instance.shouldShowSaveBookmarkDialog.set(false);
+ }}
+ edit={saveBookmarkURI != null ? bookmarks.has(saveBookmarkURI) : false}
+ onSubmit={instance.addBookmark}
+ onRemove={instance.removeBookmark}
+ />
+
+ );
+}
+
+/* @scarf-info: do not remove, more info: https://fburl.com/scarf */
+/* @scarf-generated: flipper-plugin index.js.template 0bfa32e5-fb15-4705-81f8-86260a1f3f8e */
diff --git a/desktop/plugins/public/navigation/components/AutoCompleteSheet.tsx b/desktop/plugins/public/navigation/components/AutoCompleteSheet.tsx
index 83e2aaa2e..c7bd30f73 100644
--- a/desktop/plugins/public/navigation/components/AutoCompleteSheet.tsx
+++ b/desktop/plugins/public/navigation/components/AutoCompleteSheet.tsx
@@ -50,7 +50,7 @@ const SheetItemIcon = styled.span({
padding: 8,
});
-export default (props: Props) => {
+export function AutoCompleteSheet(props: Props) {
const {providers, onHighlighted, onNavigate, query} = props;
const lineItems = filterProvidersToLineItems(providers, query, MAX_ITEMS);
lineItems.unshift({uri: query, matchPattern: query, icon: 'send'});
@@ -70,4 +70,4 @@ export default (props: Props) => {
))}
);
-};
+}
diff --git a/desktop/plugins/public/navigation/components/BookmarksSidebar.tsx b/desktop/plugins/public/navigation/components/BookmarksSidebar.tsx
index a7f9fc3f7..07c3a0bcb 100644
--- a/desktop/plugins/public/navigation/components/BookmarksSidebar.tsx
+++ b/desktop/plugins/public/navigation/components/BookmarksSidebar.tsx
@@ -78,7 +78,7 @@ const alphabetizeBookmarkCompare = (b1: Bookmark, b2: Bookmark) => {
return b1.uri < b2.uri ? -1 : b1.uri > b2.uri ? 1 : 0;
};
-export default (props: Props) => {
+export function BookmarksSidebar(props: Props) {
const {bookmarks, onNavigate, onRemove} = props;
return (
@@ -119,4 +119,4 @@ export default (props: Props) => {
);
-};
+}
diff --git a/desktop/plugins/public/navigation/components/FavoriteButton.tsx b/desktop/plugins/public/navigation/components/FavoriteButton.tsx
index 613e09eac..287ff368b 100644
--- a/desktop/plugins/public/navigation/components/FavoriteButton.tsx
+++ b/desktop/plugins/public/navigation/components/FavoriteButton.tsx
@@ -27,7 +27,7 @@ const FavoriteButtonContainer = styled.div({
},
});
-export default (props: Props) => {
+export function FavoriteButton(props: Props) {
const {highlighted, onClick, ...iconButtonProps} = props;
return (
@@ -42,4 +42,4 @@ export default (props: Props) => {
);
-};
+}
diff --git a/desktop/plugins/public/navigation/components/IconButton.tsx b/desktop/plugins/public/navigation/components/IconButton.tsx
index 1a8a067dc..f21caf849 100644
--- a/desktop/plugins/public/navigation/components/IconButton.tsx
+++ b/desktop/plugins/public/navigation/components/IconButton.tsx
@@ -43,23 +43,23 @@ const RippleEffect = styled.div({
},
});
-const IconButton = styled.div({
+const IconButtonContainer = styled.div({
':active': {
animation: `${shrinkAnimation} .25s ease forwards`,
},
});
-export default function (props: Props) {
+export function IconButton(props: Props) {
return (
-
+
-
+
);
}
diff --git a/desktop/plugins/public/navigation/components/NavigationInfoBox.tsx b/desktop/plugins/public/navigation/components/NavigationInfoBox.tsx
index e8cbf4fe6..6639f1a5f 100644
--- a/desktop/plugins/public/navigation/components/NavigationInfoBox.tsx
+++ b/desktop/plugins/public/navigation/components/NavigationInfoBox.tsx
@@ -160,7 +160,7 @@ const buildParameterTable = (parameters: Map) => {
);
};
-export default (props: Props) => {
+export function NavigationInfoBox(props: Props) {
const {
uri,
isBookmarked,
@@ -238,4 +238,4 @@ export default (props: Props) => {
);
}
-};
+}
diff --git a/desktop/plugins/public/navigation/components/RequiredParametersDialog.tsx b/desktop/plugins/public/navigation/components/RequiredParametersDialog.tsx
index b409915bd..4444dc6b7 100644
--- a/desktop/plugins/public/navigation/components/RequiredParametersDialog.tsx
+++ b/desktop/plugins/public/navigation/components/RequiredParametersDialog.tsx
@@ -28,7 +28,7 @@ type Props = {
onSubmit: (uri: URI) => void;
};
-export default (props: Props) => {
+export function RequiredParametersDialog(props: Props) {
const {onHide, onSubmit, uri, requiredParameters} = props;
const {isValid, values, setValuesArray} =
useRequiredParameterFormValidator(requiredParameters);
@@ -95,4 +95,4 @@ export default (props: Props) => {
);
-};
+}
diff --git a/desktop/plugins/public/navigation/components/SaveBookmarkDialog.tsx b/desktop/plugins/public/navigation/components/SaveBookmarkDialog.tsx
index 830097c2a..f3a01515c 100644
--- a/desktop/plugins/public/navigation/components/SaveBookmarkDialog.tsx
+++ b/desktop/plugins/public/navigation/components/SaveBookmarkDialog.tsx
@@ -48,7 +48,7 @@ const NameInput = styled(Input)({
height: 30,
});
-export default (props: Props) => {
+export function SaveBookmarkDialog(props: Props) {
const {edit, shouldShow, onHide, onRemove, onSubmit, uri} = props;
const [commonName, setCommonName] = useState('');
if (uri == null || !shouldShow) {
@@ -114,4 +114,4 @@ export default (props: Props) => {
);
}
-};
+}
diff --git a/desktop/plugins/public/navigation/components/SearchBar.tsx b/desktop/plugins/public/navigation/components/SearchBar.tsx
index 07469a6cb..7019331ae 100644
--- a/desktop/plugins/public/navigation/components/SearchBar.tsx
+++ b/desktop/plugins/public/navigation/components/SearchBar.tsx
@@ -57,7 +57,7 @@ const SearchInputContainer = styled.div({
position: 'relative',
});
-class SearchBar extends Component {
+export class SearchBar extends Component {
state = {
inputFocused: false,
autoCompleteSheetOpen: false,
@@ -158,5 +158,3 @@ class SearchBar extends Component {
);
}
}
-
-export default SearchBar;
diff --git a/desktop/plugins/public/navigation/components/Timeline.tsx b/desktop/plugins/public/navigation/components/Timeline.tsx
index 216f3e98e..f79d1b9ba 100644
--- a/desktop/plugins/public/navigation/components/Timeline.tsx
+++ b/desktop/plugins/public/navigation/components/Timeline.tsx
@@ -58,7 +58,7 @@ const NoData = styled(FlexCenter)({
color: theme.textColorSecondary,
});
-export default (props: Props) => {
+export function Timeline(props: Props) {
const {bookmarks, events, onNavigate, onFavorite} = props;
const timelineRef = useRef(null);
return events.length === 0 ? (
@@ -92,4 +92,4 @@ export default (props: Props) => {
);
-};
+}
diff --git a/desktop/plugins/public/navigation/components/index.tsx b/desktop/plugins/public/navigation/components/index.tsx
index 8d55be28d..62dca3bd7 100644
--- a/desktop/plugins/public/navigation/components/index.tsx
+++ b/desktop/plugins/public/navigation/components/index.tsx
@@ -7,12 +7,12 @@
* @format
*/
-export {default as AutoCompleteSheet} from './AutoCompleteSheet';
-export {default as BookmarksSidebar} from './BookmarksSidebar';
-export {default as FavoriteButton} from './FavoriteButton';
-export {default as IconButton} from './IconButton';
-export {default as NavigationInfoBox} from './NavigationInfoBox';
-export {default as RequiredParametersDialog} from './RequiredParametersDialog';
-export {default as SaveBookmarkDialog} from './SaveBookmarkDialog';
-export {default as SearchBar} from './SearchBar';
-export {default as Timeline} from './Timeline';
+export {AutoCompleteSheet} from './AutoCompleteSheet';
+export {BookmarksSidebar} from './BookmarksSidebar';
+export {FavoriteButton} from './FavoriteButton';
+export {IconButton} from './IconButton';
+export {NavigationInfoBox} from './NavigationInfoBox';
+export {RequiredParametersDialog} from './RequiredParametersDialog';
+export {SaveBookmarkDialog} from './SaveBookmarkDialog';
+export {SearchBar} from './SearchBar';
+export {Timeline} from './Timeline';
diff --git a/desktop/plugins/public/navigation/index.tsx b/desktop/plugins/public/navigation/index.tsx
index 4f97fe404..fa2ff8b8a 100644
--- a/desktop/plugins/public/navigation/index.tsx
+++ b/desktop/plugins/public/navigation/index.tsx
@@ -8,248 +8,5 @@
* @flow strict-local
*/
-import {bufferToBlob} from 'flipper';
-import {
- BookmarksSidebar,
- SaveBookmarkDialog,
- SearchBar,
- Timeline,
- RequiredParametersDialog,
-} from './components';
-import {
- removeBookmarkFromDB,
- readBookmarksFromDB,
- writeBookmarkToDB,
-} from './util/indexedDB';
-import {
- appMatchPatternsToAutoCompleteProvider,
- bookmarksToAutoCompleteProvider,
-} from './util/autoCompleteProvider';
-import {getAppMatchPatterns} from './util/appMatchPatterns';
-import {getRequiredParameters, filterOptionalParameters} from './util/uri';
-import {
- Bookmark,
- NavigationEvent,
- AppMatchPattern,
- URI,
- RawNavigationEvent,
-} from './types';
-import React, {useMemo} from 'react';
-import {
- PluginClient,
- createState,
- useValue,
- usePlugin,
- Layout,
- renderReactRoot,
-} from 'flipper-plugin';
-
-export type State = {
- shouldShowSaveBookmarkDialog: boolean;
- shouldShowURIErrorDialog: boolean;
- saveBookmarkURI: URI | null;
- requiredParameters: Array;
-};
-
-type Events = {
- nav_event: RawNavigationEvent;
-};
-
-type Methods = {
- navigate_to(params: {url: string}): Promise;
-};
-
-export type NavigationPlugin = ReturnType;
-
-export function plugin(client: PluginClient) {
- const bookmarks = createState(new Map(), {
- persist: 'bookmarks',
- });
- const navigationEvents = createState([], {
- persist: 'navigationEvents',
- });
- const appMatchPatterns = createState([], {
- persist: 'appMatchPatterns',
- });
- const currentURI = createState('');
- const shouldShowSaveBookmarkDialog = createState(false);
- const saveBookmarkURI = createState(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: Buffer = await client.device.realDevice.screenshot();
- const blobURL = URL.createObjectURL(bufferToBlob(screenshot));
- // 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.realDevice)
- .then((patterns) => {
- appMatchPatterns.set(patterns);
- })
- .catch((e) => {
- console.error('[Navigation] Failed to find appMatchPatterns', e);
- });
-
- readBookmarksFromDB().then((bookmarksData) => {
- bookmarks.set(bookmarksData);
- });
-
- 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.realDevice.navigateToLocation(
- filterOptionalParameters(filteredQuery),
- );
- }
- } else {
- renderReactRoot((unmount) => (
-
- ));
- }
- }
-
- 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,
- 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;
- },
- };
-}
-
-export function Component() {
- const instance = usePlugin(plugin);
- const bookmarks = useValue(instance.bookmarks);
- const appMatchPatterns = useValue(instance.appMatchPatterns);
- const saveBookmarkURI = useValue(instance.saveBookmarkURI);
- const shouldShowSaveBookmarkDialog = useValue(
- instance.shouldShowSaveBookmarkDialog,
- );
- const currentURI = useValue(instance.currentURI);
- const navigationEvents = useValue(instance.navigationEvents);
-
- const autoCompleteProviders = useMemo(
- () => [
- bookmarksToAutoCompleteProvider(bookmarks),
- appMatchPatternsToAutoCompleteProvider(appMatchPatterns),
- ],
- [bookmarks, appMatchPatterns],
- );
- return (
-
-
-
-
- {
- instance.shouldShowSaveBookmarkDialog.set(false);
- }}
- edit={saveBookmarkURI != null ? bookmarks.has(saveBookmarkURI) : false}
- onSubmit={instance.addBookmark}
- onRemove={instance.removeBookmark}
- />
-
- );
-}
-
-/* @scarf-info: do not remove, more info: https://fburl.com/scarf */
-/* @scarf-generated: flipper-plugin index.js.template 0bfa32e5-fb15-4705-81f8-86260a1f3f8e */
+export {plugin, NavigationPlugin} from './plugin';
+export {Component} from './Component';
diff --git a/desktop/plugins/public/navigation/plugin.tsx b/desktop/plugins/public/navigation/plugin.tsx
new file mode 100644
index 000000000..48b5e52dd
--- /dev/null
+++ b/desktop/plugins/public/navigation/plugin.tsx
@@ -0,0 +1,187 @@
+/**
+ * Copyright (c) Facebook, Inc. and its 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 {bufferToBlob} from 'flipper';
+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;
+};
+
+type Events = {
+ nav_event: RawNavigationEvent;
+};
+
+type Methods = {
+ navigate_to(params: {url: string}): Promise;
+};
+
+export type NavigationPlugin = ReturnType;
+
+export function plugin(client: PluginClient) {
+ const bookmarks = createState(new Map(), {
+ persist: 'bookmarks',
+ });
+ const navigationEvents = createState([], {
+ persist: 'navigationEvents',
+ });
+ const appMatchPatterns = createState([], {
+ persist: 'appMatchPatterns',
+ });
+ const currentURI = createState('');
+ const shouldShowSaveBookmarkDialog = createState(false);
+ const saveBookmarkURI = createState(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: Buffer = await client.device.realDevice.screenshot();
+ const blobURL = URL.createObjectURL(bufferToBlob(screenshot));
+ // 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.realDevice)
+ .then((patterns) => {
+ appMatchPatterns.set(patterns);
+ })
+ .catch((e) => {
+ console.error('[Navigation] Failed to find appMatchPatterns', e);
+ });
+
+ readBookmarksFromDB().then((bookmarksData) => {
+ bookmarks.set(bookmarksData);
+ });
+
+ 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.realDevice.navigateToLocation(
+ filterOptionalParameters(filteredQuery),
+ );
+ }
+ } else {
+ renderReactRoot((unmount) => (
+
+ ));
+ }
+ }
+
+ 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,
+ 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 */