1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-21 09:38:01 +02:00

Chore: Migrate mobile Dropdown, ScreenHeader to TypeScript (#6763)

This commit is contained in:
Henry Heino 2022-08-27 05:36:59 -07:00 committed by GitHub
parent 3ec3a37603
commit 92c24c2129
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 229 additions and 103 deletions

View File

@ -842,6 +842,9 @@ packages/app-mobile/components/BackButtonDialogBox.js.map
packages/app-mobile/components/CameraView.d.ts
packages/app-mobile/components/CameraView.js
packages/app-mobile/components/CameraView.js.map
packages/app-mobile/components/Dropdown.d.ts
packages/app-mobile/components/Dropdown.js
packages/app-mobile/components/Dropdown.js.map
packages/app-mobile/components/CustomButton.d.ts
packages/app-mobile/components/CustomButton.js
packages/app-mobile/components/CustomButton.js.map
@ -917,6 +920,9 @@ packages/app-mobile/components/NoteEditor/SelectionFormatting.js.map
packages/app-mobile/components/NoteEditor/types.d.ts
packages/app-mobile/components/NoteEditor/types.js
packages/app-mobile/components/NoteEditor/types.js.map
packages/app-mobile/components/ScreenHeader.d.ts
packages/app-mobile/components/ScreenHeader.js
packages/app-mobile/components/ScreenHeader.js.map
packages/app-mobile/components/SelectDateTimeDialog.d.ts
packages/app-mobile/components/SelectDateTimeDialog.js
packages/app-mobile/components/SelectDateTimeDialog.js.map

6
.gitignore vendored
View File

@ -834,6 +834,9 @@ packages/app-mobile/components/CameraView.js.map
packages/app-mobile/components/CustomButton.d.ts
packages/app-mobile/components/CustomButton.js
packages/app-mobile/components/CustomButton.js.map
packages/app-mobile/components/Dropdown.d.ts
packages/app-mobile/components/Dropdown.js
packages/app-mobile/components/Dropdown.js.map
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.d.ts
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js.map
@ -906,6 +909,9 @@ packages/app-mobile/components/NoteEditor/SelectionFormatting.js.map
packages/app-mobile/components/NoteEditor/types.d.ts
packages/app-mobile/components/NoteEditor/types.js
packages/app-mobile/components/NoteEditor/types.js.map
packages/app-mobile/components/ScreenHeader.d.ts
packages/app-mobile/components/ScreenHeader.js
packages/app-mobile/components/ScreenHeader.js.map
packages/app-mobile/components/SelectDateTimeDialog.d.ts
packages/app-mobile/components/SelectDateTimeDialog.js
packages/app-mobile/components/SelectDateTimeDialog.js.map

View File

@ -1,31 +1,60 @@
const React = require('react');
const { TouchableOpacity, TouchableWithoutFeedback, Dimensions, Text, Modal, View } = require('react-native');
import { TouchableOpacity, TouchableWithoutFeedback, Dimensions, Text, Modal, View, LayoutRectangle, ViewStyle, TextStyle } from 'react-native';
import { Component } from 'react';
const { ItemList } = require('./ItemList.js');
class Dropdown extends React.Component {
constructor() {
super();
this.headerRef_ = null;
type ValueType = string;
export interface DropdownListItem {
label: string;
value: ValueType;
}
UNSAFE_componentWillMount() {
this.setState({
export type OnValueChangedListener = (newValue: ValueType)=> void;
interface DropdownProps {
listItemStyle?: ViewStyle;
itemListStyle?: ViewStyle;
itemWrapperStyle?: ViewStyle;
headerWrapperStyle?: ViewStyle;
headerStyle?: TextStyle;
itemStyle?: TextStyle;
disabled?: boolean;
labelTransform?: 'trim';
items: DropdownListItem[];
selectedValue: ValueType|null;
onValueChange?: OnValueChangedListener;
}
interface DropdownState {
headerSize: LayoutRectangle;
listVisible: boolean;
}
class Dropdown extends Component<DropdownProps, DropdownState> {
private headerRef: TouchableOpacity;
public constructor(props: DropdownProps) {
super(props);
this.headerRef = null;
this.state = {
headerSize: { x: 0, y: 0, width: 0, height: 0 },
listVisible: false,
});
};
}
updateHeaderCoordinates() {
private updateHeaderCoordinates() {
// https://stackoverflow.com/questions/30096038/react-native-getting-the-position-of-an-element
this.headerRef_.measure((fx, fy, width, height, px, py) => {
this.headerRef.measure((_fx, _fy, width, height, px, py) => {
this.setState({
headerSize: { x: px, y: py, width: width, height: height },
});
});
}
render() {
public render() {
const items = this.props.items;
const itemHeight = 60;
const windowHeight = Dimensions.get('window').height - 50;
@ -84,23 +113,26 @@ class Dropdown extends React.Component {
}
}
if (this.props.labelTransform && this.props.labelTransform === 'trim') headerLabel = headerLabel.trim();
if (this.props.labelTransform && this.props.labelTransform === 'trim') {
headerLabel = headerLabel.trim();
}
const closeList = () => {
this.setState({ listVisible: false });
};
const itemRenderer = item => {
const itemRenderer = (item: DropdownListItem) => {
const key = item.value.toString();
return (
<TouchableOpacity
style={itemWrapperStyle}
key={item.value}
key={key}
onPress={() => {
closeList();
if (this.props.onValueChange) this.props.onValueChange(item.value);
}}
>
<Text ellipsizeMode="tail" numberOfLines={1} style={itemStyle} key={item.value}>
<Text ellipsizeMode="tail" numberOfLines={1} style={itemStyle} key={key}>
{item.label}
</Text>
</TouchableOpacity>
@ -111,7 +143,7 @@ class Dropdown extends React.Component {
<View style={{ flex: 1, flexDirection: 'column' }}>
<TouchableOpacity
style={headerWrapperStyle}
ref={ref => (this.headerRef_ = ref)}
ref={ref => (this.headerRef = ref)}
disabled={this.props.disabled}
onPress={() => {
this.updateHeaderCoordinates();
@ -141,9 +173,7 @@ class Dropdown extends React.Component {
style={itemListStyle}
items={this.props.items}
itemHeight={itemHeight}
itemRenderer={item => {
return itemRenderer(item);
}}
itemRenderer={itemRenderer}
/>
</View>
</View>
@ -154,4 +184,5 @@ class Dropdown extends React.Component {
}
}
module.exports = { Dropdown };
export default Dropdown;
export { Dropdown };

View File

@ -1,21 +1,24 @@
const React = require('react');
const { connect } = require('react-redux');
const { View, Text, StyleSheet, TouchableOpacity, Image, ScrollView, Dimensions } = require('react-native');
import { connect } from 'react-redux';
import { PureComponent, Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Image, ScrollView, Dimensions, ViewStyle } from 'react-native';
const Icon = require('react-native-vector-icons/Ionicons').default;
const { BackButtonService } = require('../services/back-button.js');
const NavService = require('@joplin/lib/services/NavService').default;
const { Menu, MenuOptions, MenuOption, MenuTrigger } = require('react-native-popup-menu');
const { _ } = require('@joplin/lib/locale');
const Setting = require('@joplin/lib/models/Setting').default;
const Note = require('@joplin/lib/models/Note').default;
const Folder = require('@joplin/lib/models/Folder').default;
import NavService from '@joplin/lib/services/NavService';
import { Menu, MenuOptions, MenuOption, MenuTrigger } from 'react-native-popup-menu';
import { _ } from '@joplin/lib/locale';
import Setting from '@joplin/lib/models/Setting';
import Note from '@joplin/lib/models/Note';
import Folder, { FolderEntityWithChildren } from '@joplin/lib/models/Folder';
const { themeStyle } = require('./global-style.js');
const { Dropdown } = require('./Dropdown.js');
import Dropdown, { DropdownListItem, OnValueChangedListener } from './Dropdown';
const { dialogs } = require('../utils/dialogs.js');
const DialogBox = require('react-native-dialogbox').default;
const { localSyncInfoFromState } = require('@joplin/lib/services/synchronizer/syncInfoUtils');
const { showMissingMasterKeyMessage } = require('@joplin/lib/services/e2ee/utils');
import { localSyncInfoFromState } from '@joplin/lib/services/synchronizer/syncInfoUtils';
import { showMissingMasterKeyMessage } from '@joplin/lib/services/e2ee/utils';
import { FolderEntity } from '@joplin/lib/services/database/types';
import { State } from '@joplin/lib/reducer';
import CustomButton from './CustomButton';
Icon.loadFont();
@ -26,20 +29,78 @@ Icon.loadFont();
// default height.
const PADDING_V = 10;
class ScreenHeaderComponent extends React.PureComponent {
constructor() {
super();
this.styles_ = {};
type OnSelectCallbackType=()=> void;
type OnPressCallback=()=> void;
interface NavButtonPressEvent {
// Name of the screen to navigate to
screen: string;
}
styles() {
interface MenuOptionType {
onPress: OnPressCallback;
isDivider?: boolean;
title: string;
}
type DispatchCommandType=(event: { type: string })=> void;
interface ScreenHeaderProps {
selectedNoteIds: string[];
noteSelectionEnabled: boolean;
parentComponent: Component;
showUndoButton: boolean;
undoButtonDisabled?: boolean;
showRedoButton: boolean;
menuOptions: MenuOptionType[];
title?: string|null;
folders: FolderEntity[];
folderPickerOptions?: {
enabled: boolean;
selectedFolderId: string;
onValueChange: OnValueChangedListener;
mustSelect?: boolean;
};
dispatch: DispatchCommandType;
onUndoButtonPress: OnPressCallback;
onRedoButtonPress: OnPressCallback;
onSaveButtonPress: OnPressCallback;
sortButton_press?: OnPressCallback;
showSideMenuButton?: boolean;
showSearchButton?: boolean;
showContextMenuButton?: boolean;
showBackButton?: boolean;
saveButtonDisabled?: boolean;
showSaveButton?: boolean;
historyCanGoBack?: boolean;
showMissingMasterKeyMessage?: boolean;
hasDisabledSyncItems?: boolean;
shouldUpgradeSyncTarget?: boolean;
showShouldUpgradeSyncTargetMessage?: boolean;
}
interface ScreenHeaderState {
}
class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeaderState> {
private cachedStyles: any;
public dialogbox?: typeof DialogBox;
public constructor(props: ScreenHeaderProps) {
super(props);
this.cachedStyles = {};
}
private styles() {
const themeId = Setting.value('theme');
if (this.styles_[themeId]) return this.styles_[themeId];
this.styles_ = {};
if (this.cachedStyles[themeId]) return this.cachedStyles[themeId];
this.cachedStyles = {};
const theme = themeStyle(themeId);
const styleObject = {
const styleObject: any = {
container: {
flexDirection: 'column',
backgroundColor: theme.backgroundColor2,
@ -148,15 +209,15 @@ class ScreenHeaderComponent extends React.PureComponent {
styleObject.saveButtonDisabled = Object.assign({}, styleObject.saveButton, { opacity: theme.disabledOpacity });
styleObject.iconButtonDisabled = Object.assign({}, styleObject.iconButton, { opacity: theme.disabledOpacity });
this.styles_[themeId] = StyleSheet.create(styleObject);
return this.styles_[themeId];
this.cachedStyles[themeId] = StyleSheet.create(styleObject);
return this.cachedStyles[themeId];
}
sideMenuButton_press() {
private sideMenuButton_press() {
this.props.dispatch({ type: 'SIDE_MENU_TOGGLE' });
}
async backButton_press() {
private async backButton_press() {
if (this.props.noteSelectionEnabled) {
this.props.dispatch({ type: 'NOTE_SELECTION_END' });
} else {
@ -164,15 +225,15 @@ class ScreenHeaderComponent extends React.PureComponent {
}
}
selectAllButton_press() {
private selectAllButton_press() {
this.props.dispatch({ type: 'NOTE_SELECT_ALL_TOGGLE' });
}
searchButton_press() {
NavService.go('Search');
private searchButton_press() {
void NavService.go('Search');
}
async duplicateButton_press() {
private async duplicateButton_press() {
const noteIds = this.props.selectedNoteIds;
// Duplicate all selected notes. ensureUniqueTitle is set to true to use the
@ -182,7 +243,7 @@ class ScreenHeaderComponent extends React.PureComponent {
this.props.dispatch({ type: 'NOTE_SELECTION_END' });
}
async deleteButton_press() {
private async deleteButton_press() {
// Dialog needs to be displayed as a child of the parent component, otherwise
// it won't be visible within the header component.
const noteIds = this.props.selectedNoteIds;
@ -197,25 +258,17 @@ class ScreenHeaderComponent extends React.PureComponent {
await Note.batchDelete(noteIds);
}
menu_select(value) {
private menu_select(value: OnSelectCallbackType) {
if (typeof value === 'function') {
value();
}
}
log_press() {
NavService.go('Log');
private warningBox_press(event: NavButtonPressEvent) {
void NavService.go(event.screen);
}
status_press() {
NavService.go('Status');
}
warningBox_press(event) {
NavService.go(event.screen);
}
renderWarningBox(screen, message) {
private renderWarningBox(screen: string, message: string) {
return (
<TouchableOpacity key={screen} style={this.styles().warningBox} onPress={() => this.warningBox_press({ screen: screen })} activeOpacity={0.8}>
<Text style={{ flex: 1 }}>{message}</Text>
@ -223,9 +276,9 @@ class ScreenHeaderComponent extends React.PureComponent {
);
}
render() {
public render() {
const themeId = Setting.value('theme');
function sideMenuButton(styles, onPress) {
function sideMenuButton(styles: any, onPress: OnPressCallback) {
return (
<TouchableOpacity
onPress={onPress}
@ -240,7 +293,7 @@ class ScreenHeaderComponent extends React.PureComponent {
);
}
function backButton(styles, onPress, disabled) {
function backButton(styles: any, onPress: OnPressCallback, disabled: boolean) {
return (
<TouchableOpacity
onPress={onPress}
@ -259,7 +312,9 @@ class ScreenHeaderComponent extends React.PureComponent {
);
}
function saveButton(styles, onPress, disabled, show) {
function saveButton(
styles: any, onPress: OnPressCallback, disabled: boolean, show: boolean
) {
if (!show) return null;
const icon = disabled ? <Icon name="md-checkmark" style={styles.savedButtonIcon} /> : <Image style={styles.saveButtonIcon} source={require('./SaveIcon.png')} />;
@ -278,7 +333,14 @@ class ScreenHeaderComponent extends React.PureComponent {
);
}
const renderTopButton = (options) => {
interface TopButtonOptions {
visible: boolean;
iconName: string;
disabled?: boolean;
description: string;
onPress: OnPressCallback;
}
const renderTopButton = (options: TopButtonOptions) => {
if (!options.visible) return null;
const icon = <Icon name={options.iconName} style={this.styles().topIcon} />;
@ -317,7 +379,7 @@ class ScreenHeaderComponent extends React.PureComponent {
});
};
function selectAllButton(styles, onPress) {
function selectAllButton(styles: any, onPress: OnPressCallback) {
return (
<CustomButton
onPress={onPress}
@ -331,7 +393,7 @@ class ScreenHeaderComponent extends React.PureComponent {
);
}
function searchButton(styles, onPress) {
function searchButton(styles: any, onPress: OnPressCallback) {
return (
<CustomButton
onPress={onPress}
@ -345,7 +407,7 @@ class ScreenHeaderComponent extends React.PureComponent {
);
}
function deleteButton(styles, onPress, disabled) {
function deleteButton(styles: any, onPress: OnPressCallback, disabled: boolean) {
return (
<CustomButton
onPress={onPress}
@ -363,7 +425,7 @@ class ScreenHeaderComponent extends React.PureComponent {
);
}
function duplicateButton(styles, onPress, disabled) {
function duplicateButton(styles: any, onPress: OnPressCallback, disabled: boolean) {
return (
<CustomButton
onPress={onPress}
@ -381,7 +443,7 @@ class ScreenHeaderComponent extends React.PureComponent {
);
}
function sortButton(styles, onPress) {
function sortButton(styles: any, onPress: OnPressCallback) {
return (
<TouchableOpacity
onPress={onPress}
@ -430,12 +492,15 @@ class ScreenHeaderComponent extends React.PureComponent {
);
}
const createTitleComponent = (disabled) => {
const createTitleComponent = (disabled: boolean) => {
const themeId = Setting.value('theme');
const theme = themeStyle(themeId);
const folderPickerOptions = this.props.folderPickerOptions;
if (folderPickerOptions && folderPickerOptions.enabled) {
const addFolderChildren = (folders, pickerItems, indent) => {
const addFolderChildren = (
folders: FolderEntityWithChildren[], pickerItems: DropdownListItem[], indent: number
) => {
folders.sort((a, b) => {
const aTitle = a && a.title ? a.title : '';
const bTitle = b && b.title ? b.title : '';
@ -453,7 +518,7 @@ class ScreenHeaderComponent extends React.PureComponent {
return pickerItems;
};
const titlePickerItems = mustSelect => {
const titlePickerItems = (mustSelect: boolean) => {
const folders = this.props.folders.filter(f => f.id !== Folder.conflictFolderId());
let output = [];
if (mustSelect) output.push({ label: _('Move to notebook...'), value: null });
@ -465,7 +530,6 @@ class ScreenHeaderComponent extends React.PureComponent {
return (
<Dropdown
items={titlePickerItems(!!folderPickerOptions.mustSelect)}
itemHeight={35}
disabled={disabled}
labelTransform="trim"
selectedValue={'selectedFolderId' in folderPickerOptions ? folderPickerOptions.selectedFolderId : null}
@ -481,13 +545,13 @@ class ScreenHeaderComponent extends React.PureComponent {
color: theme.color,
fontSize: theme.fontSize,
}}
onValueChange={async (folderId, itemIndex) => {
onValueChange={async (folderId) => {
// If onValueChange is specified, use this as a callback, otherwise do the default
// which is to take the selectedNoteIds from the state and move them to the
// chosen folder.
if (folderPickerOptions.onValueChange) {
folderPickerOptions.onValueChange(folderId, itemIndex);
folderPickerOptions.onValueChange(folderId);
return;
}
@ -527,7 +591,7 @@ class ScreenHeaderComponent extends React.PureComponent {
let backButtonDisabled = !this.props.historyCanGoBack;
if (this.props.noteSelectionEnabled) backButtonDisabled = false;
const headerItemDisabled = !this.props.selectedNoteIds.length > 0;
const headerItemDisabled = !(this.props.selectedNoteIds.length > 0);
const titleComp = createTitleComponent(headerItemDisabled);
const sideMenuComp = !showSideMenuButton ? null : sideMenuButton(this.styles(), () => this.sideMenuButton_press());
@ -539,7 +603,10 @@ class ScreenHeaderComponent extends React.PureComponent {
const sortButtonComp = !this.props.noteSelectionEnabled && this.props.sortButton_press ? sortButton(this.styles(), () => this.props.sortButton_press()) : null;
const windowHeight = Dimensions.get('window').height - 50;
const contextMenuStyle = { paddingTop: PADDING_V, paddingBottom: PADDING_V };
const contextMenuStyle: ViewStyle = {
paddingTop: PADDING_V,
paddingBottom: PADDING_V,
};
// HACK: if this button is removed during selection mode, the header layout is broken, so for now just make it 1 pixel large (normally it should be hidden)
if (this.props.noteSelectionEnabled) contextMenuStyle.width = 1;
@ -561,8 +628,8 @@ class ScreenHeaderComponent extends React.PureComponent {
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
{sideMenuComp}
{backButtonComp}
{renderUndoButton(this.styles())}
{renderRedoButton(this.styles())}
{renderUndoButton()}
{renderRedoButton()}
{saveButton(
this.styles(),
() => {
@ -581,20 +648,20 @@ class ScreenHeaderComponent extends React.PureComponent {
</View>
{warningComps}
<DialogBox
ref={dialogbox => {
ref={(dialogbox: typeof DialogBox) => {
this.dialogbox = dialogbox;
}}
/>
</View>
);
}
}
ScreenHeaderComponent.defaultProps = {
public static defaultProps: Partial<ScreenHeaderProps> ={
menuOptions: [],
};
}
const ScreenHeader = connect(state => {
const ScreenHeader = connect((state: State) => {
const syncInfo = localSyncInfoFromState(state);
return {
@ -610,4 +677,5 @@ const ScreenHeader = connect(state => {
};
})(ScreenHeaderComponent);
module.exports = { ScreenHeader };
export default ScreenHeader;
export { ScreenHeader };

View File

@ -14,7 +14,7 @@ import { reg } from '@joplin/lib/registry';
import { State } from '@joplin/lib/reducer';
const VersionInfo = require('react-native-version-info').default;
const { connect } = require('react-redux');
const { ScreenHeader } = require('../screen-header.js');
import ScreenHeader from '../ScreenHeader';
const { _ } = require('@joplin/lib/locale');
const { BaseScreenComponent } = require('../base-screen.js');
const { Dropdown } = require('../Dropdown.js');
@ -461,7 +461,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
color: theme.color,
fontSize: theme.fontSize,
}}
onValueChange={(itemValue: any) => {
onValueChange={(itemValue: string) => {
updateSettingValue(key, itemValue);
}}
/>

View File

@ -26,7 +26,7 @@ import BaseModel from '@joplin/lib/BaseModel';
const { ActionButton } = require('../action-button.js');
const { fileExtension, safeFileExtension } = require('@joplin/lib/path-utils');
const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
const { ScreenHeader } = require('../screen-header.js');
import ScreenHeader from '../ScreenHeader';
const NoteTagsDialog = require('./NoteTagsDialog');
import time from '@joplin/lib/time';
const { Checkbox } = require('../checkbox.js');

View File

@ -5,7 +5,7 @@ const { View, Text, ScrollView } = require('react-native');
const { connect } = require('react-redux');
const { themeStyle } = require('../global-style.js');
const { ScreenHeader } = require('../screen-header.js');
import ScreenHeader from '../ScreenHeader';
function UpgradeSyncTargetScreen(props: any) {
const upgradeResult = useSyncTargetUpgrade();

View File

@ -2,7 +2,7 @@ const React = require('react');
const { View, Button, Text, TextInput, TouchableOpacity, StyleSheet, ScrollView } = require('react-native');
const { connect } = require('react-redux');
const { ScreenHeader } = require('../screen-header.js');
const { ScreenHeader } = require('../ScreenHeader');
const { _ } = require('@joplin/lib/locale');
const { BaseScreenComponent } = require('../base-screen.js');
const DialogBox = require('react-native-dialogbox').default;

View File

@ -1,7 +1,7 @@
const React = require('react');
const { TextInput, TouchableOpacity, Linking, View, StyleSheet, Text, Button, ScrollView } = require('react-native');
const { connect } = require('react-redux');
const { ScreenHeader } = require('../screen-header.js');
import ScreenHeader from '../ScreenHeader';
const { themeStyle } = require('../global-style.js');
const DialogBox = require('react-native-dialogbox').default;
const { dialogs } = require('../../utils/dialogs.js');

View File

@ -4,7 +4,7 @@ const { View, TextInput, StyleSheet } = require('react-native');
const { connect } = require('react-redux');
const Folder = require('@joplin/lib/models/Folder').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const { ScreenHeader } = require('../screen-header.js');
const { ScreenHeader } = require('../ScreenHeader');
const { BaseScreenComponent } = require('../base-screen.js');
const { dialogs } = require('../../utils/dialogs.js');
const { themeStyle } = require('../global-style.js');

View File

@ -3,7 +3,7 @@ const React = require('react');
const { FlatList, View, Text, Button, StyleSheet, Platform } = require('react-native');
const { connect } = require('react-redux');
const { reg } = require('@joplin/lib/registry.js');
const { ScreenHeader } = require('../screen-header.js');
const { ScreenHeader } = require('../ScreenHeader');
const time = require('@joplin/lib/time').default;
const { themeStyle } = require('../global-style.js');
const Logger = require('@joplin/lib/Logger').default;

View File

@ -9,7 +9,7 @@ const Tag = require('@joplin/lib/models/Tag').default;
const Note = require('@joplin/lib/models/Note').default;
const Setting = require('@joplin/lib/models/Setting').default;
const { themeStyle } = require('../global-style.js');
const { ScreenHeader } = require('../screen-header.js');
const { ScreenHeader } = require('../ScreenHeader');
const { _ } = require('@joplin/lib/locale');
const { ActionButton } = require('../action-button.js');
const { dialogs } = require('../../utils/dialogs.js');

View File

@ -4,7 +4,7 @@ const { View } = require('react-native');
const { Button } = require('react-native');
const { WebView } = require('react-native-webview');
const { connect } = require('react-redux');
const { ScreenHeader } = require('../screen-header.js');
const { ScreenHeader } = require('../ScreenHeader');
const { reg } = require('@joplin/lib/registry.js');
const { _ } = require('@joplin/lib/locale');
const { BaseScreenComponent } = require('../base-screen.js');

View File

@ -2,7 +2,7 @@ const React = require('react');
const { StyleSheet, View, TextInput, FlatList, TouchableHighlight } = require('react-native');
const { connect } = require('react-redux');
const { ScreenHeader } = require('../screen-header.js');
const { ScreenHeader } = require('../ScreenHeader');
const Icon = require('react-native-vector-icons/Ionicons').default;
const { _ } = require('@joplin/lib/locale');
const Note = require('@joplin/lib/models/Note').default;

View File

@ -3,7 +3,7 @@ const React = require('react');
const { View, Text, Button, FlatList } = require('react-native');
const Setting = require('@joplin/lib/models/Setting').default;
const { connect } = require('react-redux');
const { ScreenHeader } = require('../screen-header.js');
const { ScreenHeader } = require('../ScreenHeader');
const ReportService = require('@joplin/lib/services/ReportService').default;
const { _ } = require('@joplin/lib/locale');
const { BaseScreenComponent } = require('../base-screen.js');

View File

@ -4,7 +4,7 @@ const { View, Text, FlatList, StyleSheet, TouchableOpacity } = require('react-na
const { connect } = require('react-redux');
const Tag = require('@joplin/lib/models/Tag').default;
const { themeStyle } = require('../global-style.js');
const { ScreenHeader } = require('../screen-header.js');
const { ScreenHeader } = require('../ScreenHeader');
const { _ } = require('@joplin/lib/locale');
const { BaseScreenComponent } = require('../base-screen.js');

View File

@ -91,6 +91,7 @@
"@lezer/highlight": "^1.0.0",
"@types/jest": "^28.1.3",
"@types/react-native": "^0.64.4",
"@types/react-redux": "^7.1.24",
"babel-plugin-module-resolver": "^4.1.0",
"execa": "^4.0.0",
"fs-extra": "^8.1.0",

View File

@ -14,7 +14,7 @@ const { substrWithEllipsis } = require('../string-utils.js');
const logger = Logger.create('models/Folder');
interface FolderEntityWithChildren extends FolderEntity {
export interface FolderEntityWithChildren extends FolderEntity {
children?: FolderEntity[];
}
@ -609,7 +609,7 @@ export default class Folder extends BaseItem {
return output.join(' / ');
}
static buildTree(folders: FolderEntity[]) {
static buildTree(folders: FolderEntity[]): FolderEntityWithChildren[] {
const idToFolders: Record<string, any> = {};
for (let i = 0; i < folders.length; i++) {
idToFolders[folders[i].id] = Object.assign({}, folders[i]);

View File

@ -52,6 +52,7 @@ interface StateResourceFetcher {
export interface State {
notes: any[];
noteSelectionEnabled?: boolean;
notesSource: string;
notesParentType: string;
folders: any[];

View File

@ -4081,6 +4081,7 @@ __metadata:
"@react-native-community/slider": ^3.0.3
"@types/jest": ^28.1.3
"@types/react-native": ^0.64.4
"@types/react-redux": ^7.1.24
assert-browserify: ^2.0.0
babel-plugin-module-resolver: ^4.1.0
buffer: ^5.0.8
@ -6956,6 +6957,18 @@ __metadata:
languageName: node
linkType: hard
"@types/react-redux@npm:^7.1.24":
version: 7.1.24
resolution: "@types/react-redux@npm:7.1.24"
dependencies:
"@types/hoist-non-react-statics": ^3.3.0
"@types/react": "*"
hoist-non-react-statics: ^3.3.0
redux: ^4.0.0
checksum: 6582246581331ac7fbbd44aa1f1c136c8a9c8febbcf462432ac81302263308c21e1a2e7868beb7f73bbcb52a8e67935d133cb37f5bdcb6564eaff3a811805101
languageName: node
linkType: hard
"@types/react-test-renderer@npm:*":
version: 17.0.1
resolution: "@types/react-test-renderer@npm:17.0.1"