Refactor plugin to make it fast refreshable
Summary: Refactored Navigation plugin to make it fast-refreshable: moved the main component into a separate file and exported all components as named functions. Without these changes every change of UI triggered full reload. Reviewed By: timur-valiev Differential Revision: D29814077 fbshipit-source-id: 5285bdc5f14a5163f9501c0d45a3affefb08fc8e
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a78b6124d7
commit
d782f19001
78
desktop/plugins/public/navigation/Component.tsx
Normal file
78
desktop/plugins/public/navigation/Component.tsx
Normal file
@@ -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 (
|
||||
<Layout.Container grow>
|
||||
<SearchBar
|
||||
providers={autoCompleteProviders}
|
||||
bookmarks={bookmarks}
|
||||
onNavigate={instance.navigateTo}
|
||||
onFavorite={instance.onFavorite}
|
||||
uriFromAbove={currentURI}
|
||||
/>
|
||||
<Timeline
|
||||
bookmarks={bookmarks}
|
||||
events={navigationEvents}
|
||||
onNavigate={instance.navigateTo}
|
||||
onFavorite={instance.onFavorite}
|
||||
/>
|
||||
<BookmarksSidebar
|
||||
bookmarks={bookmarks}
|
||||
onRemove={instance.removeBookmark}
|
||||
onNavigate={instance.navigateTo}
|
||||
/>
|
||||
<SaveBookmarkDialog
|
||||
shouldShow={shouldShowSaveBookmarkDialog}
|
||||
uri={saveBookmarkURI}
|
||||
onHide={() => {
|
||||
instance.shouldShowSaveBookmarkDialog.set(false);
|
||||
}}
|
||||
edit={saveBookmarkURI != null ? bookmarks.has(saveBookmarkURI) : false}
|
||||
onSubmit={instance.addBookmark}
|
||||
onRemove={instance.removeBookmark}
|
||||
/>
|
||||
</Layout.Container>
|
||||
);
|
||||
}
|
||||
|
||||
/* @scarf-info: do not remove, more info: https://fburl.com/scarf */
|
||||
/* @scarf-generated: flipper-plugin index.js.template 0bfa32e5-fb15-4705-81f8-86260a1f3f8e */
|
||||
@@ -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) => {
|
||||
))}
|
||||
</AutoCompleteSheetContainer>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<DetailSidebar>
|
||||
@@ -119,4 +119,4 @@ export default (props: Props) => {
|
||||
</Panel>
|
||||
</DetailSidebar>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ const FavoriteButtonContainer = styled.div({
|
||||
},
|
||||
});
|
||||
|
||||
export default (props: Props) => {
|
||||
export function FavoriteButton(props: Props) {
|
||||
const {highlighted, onClick, ...iconButtonProps} = props;
|
||||
return (
|
||||
<FavoriteButtonContainer>
|
||||
@@ -42,4 +42,4 @@ export default (props: Props) => {
|
||||
<IconButton outline icon="star" onClick={onClick} {...iconButtonProps} />
|
||||
</FavoriteButtonContainer>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<RippleEffect>
|
||||
<IconButton className="icon-button" onClick={props.onClick}>
|
||||
<IconButtonContainer className="icon-button" onClick={props.onClick}>
|
||||
<Glyph
|
||||
name={props.icon}
|
||||
size={props.size}
|
||||
color={props.color}
|
||||
variant={props.outline ? 'outline' : 'filled'}
|
||||
/>
|
||||
</IconButton>
|
||||
</IconButtonContainer>
|
||||
</RippleEffect>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ const buildParameterTable = (parameters: Map<string, string>) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default (props: Props) => {
|
||||
export function NavigationInfoBox(props: Props) {
|
||||
const {
|
||||
uri,
|
||||
isBookmarked,
|
||||
@@ -238,4 +238,4 @@ export default (props: Props) => {
|
||||
</NavigationInfoBoxContainer>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
</Layout.Container>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
</Sheet>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ const SearchInputContainer = styled.div({
|
||||
position: 'relative',
|
||||
});
|
||||
|
||||
class SearchBar extends Component<Props, State> {
|
||||
export class SearchBar extends Component<Props, State> {
|
||||
state = {
|
||||
inputFocused: false,
|
||||
autoCompleteSheetOpen: false,
|
||||
@@ -158,5 +158,3 @@ class SearchBar extends Component<Props, State> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SearchBar;
|
||||
|
||||
@@ -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<HTMLDivElement>(null);
|
||||
return events.length === 0 ? (
|
||||
@@ -92,4 +92,4 @@ export default (props: Props) => {
|
||||
</div>
|
||||
</TimelineContainer>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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<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: 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) => (
|
||||
<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;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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 (
|
||||
<Layout.Container>
|
||||
<SearchBar
|
||||
providers={autoCompleteProviders}
|
||||
bookmarks={bookmarks}
|
||||
onNavigate={instance.navigateTo}
|
||||
onFavorite={instance.onFavorite}
|
||||
uriFromAbove={currentURI}
|
||||
/>
|
||||
<Timeline
|
||||
bookmarks={bookmarks}
|
||||
events={navigationEvents}
|
||||
onNavigate={instance.navigateTo}
|
||||
onFavorite={instance.onFavorite}
|
||||
/>
|
||||
<BookmarksSidebar
|
||||
bookmarks={bookmarks}
|
||||
onRemove={instance.removeBookmark}
|
||||
onNavigate={instance.navigateTo}
|
||||
/>
|
||||
<SaveBookmarkDialog
|
||||
shouldShow={shouldShowSaveBookmarkDialog}
|
||||
uri={saveBookmarkURI}
|
||||
onHide={() => {
|
||||
instance.shouldShowSaveBookmarkDialog.set(false);
|
||||
}}
|
||||
edit={saveBookmarkURI != null ? bookmarks.has(saveBookmarkURI) : false}
|
||||
onSubmit={instance.addBookmark}
|
||||
onRemove={instance.removeBookmark}
|
||||
/>
|
||||
</Layout.Container>
|
||||
);
|
||||
}
|
||||
|
||||
/* @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';
|
||||
|
||||
187
desktop/plugins/public/navigation/plugin.tsx
Normal file
187
desktop/plugins/public/navigation/plugin.tsx
Normal file
@@ -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<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: 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) => (
|
||||
<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 */
|
||||
Reference in New Issue
Block a user