You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-06-15 23:00:36 +02:00
248 lines
6.9 KiB
JavaScript
248 lines
6.9 KiB
JavaScript
const React = require("react");
|
|
const Component = React.Component;
|
|
const { View, Button, Text } = require("react-native");
|
|
const { stateUtils } = require("lib/reducer.js");
|
|
const { connect } = require("react-redux");
|
|
const { reg } = require("lib/registry.js");
|
|
const { Log } = require("lib/log.js");
|
|
const { NoteList } = require("lib/components/note-list.js");
|
|
const Folder = require("lib/models/Folder.js");
|
|
const Tag = require("lib/models/Tag.js");
|
|
const Note = require("lib/models/Note.js");
|
|
const Setting = require("lib/models/Setting.js");
|
|
const { themeStyle } = require("lib/components/global-style.js");
|
|
const { ScreenHeader } = require("lib/components/screen-header.js");
|
|
const { MenuOption } = require("react-native-popup-menu");
|
|
const { _ } = require("lib/locale.js");
|
|
const { ActionButton } = require("lib/components/action-button.js");
|
|
const { dialogs } = require("lib/dialogs.js");
|
|
const DialogBox = require("react-native-dialogbox").default;
|
|
const { BaseScreenComponent } = require("lib/components/base-screen.js");
|
|
|
|
class NotesScreenComponent extends BaseScreenComponent {
|
|
static navigationOptions(options) {
|
|
return { header: null };
|
|
}
|
|
|
|
constructor() {
|
|
super();
|
|
|
|
this.sortButton_press = async () => {
|
|
const buttons = [];
|
|
const sortNoteOptions = Setting.enumOptions("notes.sortOrder.field");
|
|
|
|
const makeCheckboxText = function(selected, sign, label) {
|
|
const s = sign === "tick" ? "✓" : "⬤";
|
|
return (selected ? s + " " : "") + label;
|
|
};
|
|
|
|
for (let field in sortNoteOptions) {
|
|
if (!sortNoteOptions.hasOwnProperty(field)) continue;
|
|
buttons.push({
|
|
text: makeCheckboxText(Setting.value("notes.sortOrder.field") === field, "bullet", sortNoteOptions[field]),
|
|
id: { name: "notes.sortOrder.field", value: field },
|
|
});
|
|
}
|
|
|
|
buttons.push({
|
|
text: makeCheckboxText(Setting.value("notes.sortOrder.reverse"), "tick", "[ " + Setting.settingMetadata("notes.sortOrder.reverse").label() + " ]"),
|
|
id: { name: "notes.sortOrder.reverse", value: !Setting.value("notes.sortOrder.reverse") },
|
|
});
|
|
|
|
buttons.push({
|
|
text: makeCheckboxText(Setting.value("uncompletedTodosOnTop"), "tick", "[ " + Setting.settingMetadata("uncompletedTodosOnTop").label() + " ]"),
|
|
id: { name: "uncompletedTodosOnTop", value: !Setting.value("uncompletedTodosOnTop") },
|
|
});
|
|
|
|
const r = await dialogs.pop(this, Setting.settingMetadata("notes.sortOrder.field").label(), buttons);
|
|
if (!r) return;
|
|
|
|
Setting.setValue(r.name, r.value);
|
|
};
|
|
}
|
|
|
|
async componentDidMount() {
|
|
await this.refreshNotes();
|
|
}
|
|
|
|
async componentWillReceiveProps(newProps) {
|
|
if (
|
|
newProps.notesOrder !== this.props.notesOrder ||
|
|
newProps.selectedFolderId != this.props.selectedFolderId ||
|
|
newProps.selectedTagId != this.props.selectedTagId ||
|
|
newProps.notesParentType != this.props.notesParentType
|
|
) {
|
|
await this.refreshNotes(newProps);
|
|
}
|
|
}
|
|
|
|
async refreshNotes(props = null) {
|
|
if (props === null) props = this.props;
|
|
|
|
let options = {
|
|
order: props.notesOrder,
|
|
uncompletedTodosOnTop: props.uncompletedTodosOnTop,
|
|
caseInsensitive: true,
|
|
};
|
|
|
|
const parent = this.parentItem(props);
|
|
if (!parent) return;
|
|
|
|
const source = JSON.stringify({
|
|
options: options,
|
|
parentId: parent.id,
|
|
});
|
|
|
|
if (source == props.notesSource) return;
|
|
|
|
let notes = [];
|
|
if (props.notesParentType == "Folder") {
|
|
notes = await Note.previews(props.selectedFolderId, options);
|
|
} else {
|
|
notes = await Tag.notes(props.selectedTagId); // TODO: should also return previews
|
|
}
|
|
|
|
this.props.dispatch({
|
|
type: "NOTE_UPDATE_ALL",
|
|
notes: notes,
|
|
notesSource: source,
|
|
});
|
|
}
|
|
|
|
deleteFolder_onPress(folderId) {
|
|
dialogs.confirm(this, _("Delete notebook? All notes within this notebook will also be deleted.")).then(ok => {
|
|
if (!ok) return;
|
|
|
|
Folder.delete(folderId)
|
|
.then(() => {
|
|
this.props.dispatch({
|
|
type: "NAV_GO",
|
|
routeName: "Welcome",
|
|
});
|
|
})
|
|
.catch(error => {
|
|
alert(error.message);
|
|
});
|
|
});
|
|
}
|
|
|
|
editFolder_onPress(folderId) {
|
|
this.props.dispatch({
|
|
type: "NAV_GO",
|
|
routeName: "Folder",
|
|
folderId: folderId,
|
|
});
|
|
}
|
|
|
|
menuOptions() {
|
|
if (this.props.notesParentType == "Folder") {
|
|
if (this.props.selectedFolderId == Folder.conflictFolderId()) return [];
|
|
|
|
const folder = this.parentItem();
|
|
if (!folder) return [];
|
|
|
|
let output = [];
|
|
if (!folder.encryption_applied)
|
|
output.push({
|
|
title: _("Edit notebook"),
|
|
onPress: () => {
|
|
this.editFolder_onPress(this.props.selectedFolderId);
|
|
},
|
|
});
|
|
output.push({
|
|
title: _("Delete notebook"),
|
|
onPress: () => {
|
|
this.deleteFolder_onPress(this.props.selectedFolderId);
|
|
},
|
|
});
|
|
|
|
return output;
|
|
} else {
|
|
return []; // For tags - TODO
|
|
}
|
|
}
|
|
|
|
parentItem(props = null) {
|
|
if (!props) props = this.props;
|
|
|
|
let output = null;
|
|
if (props.notesParentType == "Folder") {
|
|
output = Folder.byId(props.folders, props.selectedFolderId);
|
|
} else if (props.notesParentType == "Tag") {
|
|
output = Tag.byId(props.tags, props.selectedTagId);
|
|
} else {
|
|
return null;
|
|
throw new Error("Invalid parent type: " + props.notesParentType);
|
|
}
|
|
return output;
|
|
}
|
|
|
|
render() {
|
|
const parent = this.parentItem();
|
|
const theme = themeStyle(this.props.theme);
|
|
|
|
let rootStyle = {
|
|
flex: 1,
|
|
backgroundColor: theme.backgroundColor,
|
|
};
|
|
|
|
if (!this.props.visible) {
|
|
rootStyle.flex = 0.001; // This is a bit of a hack but it seems to work fine - it makes the component invisible but without unmounting it
|
|
}
|
|
|
|
if (!parent) {
|
|
return (
|
|
<View style={rootStyle}>
|
|
<ScreenHeader title={title} menuOptions={this.menuOptions()} />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
let title = parent ? parent.title : null;
|
|
const addFolderNoteButtons = this.props.selectedFolderId && this.props.selectedFolderId != Folder.conflictFolderId();
|
|
const thisComp = this;
|
|
const actionButtonComp = this.props.noteSelectionEnabled ? null : <ActionButton addFolderNoteButtons={addFolderNoteButtons} parentFolderId={this.props.selectedFolderId} />;
|
|
|
|
return (
|
|
<View style={rootStyle}>
|
|
<ScreenHeader
|
|
title={title}
|
|
menuOptions={this.menuOptions()}
|
|
parentComponent={thisComp}
|
|
sortButton_press={this.sortButton_press}
|
|
folderPickerOptions={{
|
|
enabled: this.props.noteSelectionEnabled,
|
|
mustSelect: true,
|
|
}}
|
|
/>
|
|
<NoteList style={{ flex: 1 }} />
|
|
{actionButtonComp}
|
|
<DialogBox
|
|
ref={dialogbox => {
|
|
this.dialogbox = dialogbox;
|
|
}}
|
|
/>
|
|
</View>
|
|
);
|
|
}
|
|
}
|
|
|
|
const NotesScreen = connect(state => {
|
|
return {
|
|
folders: state.folders,
|
|
tags: state.tags,
|
|
selectedFolderId: state.selectedFolderId,
|
|
selectedNoteIds: state.selectedNoteIds,
|
|
selectedTagId: state.selectedTagId,
|
|
notesParentType: state.notesParentType,
|
|
notes: state.notes,
|
|
notesSource: state.notesSource,
|
|
uncompletedTodosOnTop: state.settings.uncompletedTodosOnTop,
|
|
theme: state.settings.theme,
|
|
noteSelectionEnabled: state.noteSelectionEnabled,
|
|
notesOrder: stateUtils.notesOrder(state.settings),
|
|
};
|
|
})(NotesScreenComponent);
|
|
|
|
module.exports = { NotesScreen };
|