mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
This commit is contained in:
parent
dc96811940
commit
3983a3a52f
@ -1,6 +1,6 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import goToNote from './util/goToNote';
|
||||
import goToNote, { GotoNoteOptions } from './util/goToNote';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
|
||||
@ -12,7 +12,7 @@ export const declaration: CommandDeclaration = {
|
||||
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (_context: CommandContext, body = '', todo = false) => {
|
||||
execute: async (_context: CommandContext, body = '', todo = false, options: GotoNoteOptions = null) => {
|
||||
const folderId = Setting.value('activeFolderId');
|
||||
if (!folderId) {
|
||||
logger.warn('Not creating new note -- no active folder ID.');
|
||||
@ -26,7 +26,7 @@ export const runtime = (): CommandRuntime => {
|
||||
}, { provisional: true });
|
||||
|
||||
logger.info(`Navigating to note ${note.id}`);
|
||||
await goToNote(note.id, '');
|
||||
await goToNote(note.id, '', options);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -1,7 +1,17 @@
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import NavService from '@joplin/lib/services/NavService';
|
||||
import { AttachFileAction } from '../../components/screens/Note/commands/attachFile';
|
||||
|
||||
export interface GotoNoteOptions {
|
||||
attachFileAction?: AttachFileAction | null;
|
||||
}
|
||||
|
||||
const goToNote = async (id: string, hash?: string, options: GotoNoteOptions = null) => {
|
||||
options = {
|
||||
attachFileAction: null,
|
||||
...options,
|
||||
};
|
||||
|
||||
const goToNote = async (id: string, hash?: string) => {
|
||||
if (!(await Note.load(id))) {
|
||||
throw new Error(`No note with id ${id}`);
|
||||
}
|
||||
@ -9,6 +19,7 @@ const goToNote = async (id: string, hash?: string) => {
|
||||
return NavService.go('Note', {
|
||||
noteId: id,
|
||||
noteHash: hash,
|
||||
newNoteAttachFileAction: options.attachFileAction,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -62,6 +62,7 @@ import { CameraResult } from '../../CameraView/types';
|
||||
import { DialogContext, DialogControl } from '../../DialogManager';
|
||||
import { CommandRuntimeProps, EditorMode, PickerResponse } from './types';
|
||||
import commands from './commands';
|
||||
import { AttachFileAction, AttachFileOptions } from './commands/attachFile';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
const emptyArray: any[] = [];
|
||||
@ -83,6 +84,7 @@ interface Props extends BaseProps {
|
||||
highlightedWords: string[];
|
||||
noteHash: string;
|
||||
toolbarEnabled: boolean;
|
||||
newNoteAttachFileAction: AttachFileAction;
|
||||
}
|
||||
|
||||
interface ComponentProps extends Props {
|
||||
@ -523,6 +525,19 @@ class NoteScreenComponent extends BaseScreenComponent<ComponentProps, State> imp
|
||||
// has already been granted, it doesn't slow down opening the note. If it hasn't
|
||||
// been granted, the popup will open anyway.
|
||||
void this.requestGeoLocationPermissions();
|
||||
|
||||
if (this.props.newNoteAttachFileAction) {
|
||||
setTimeout(async () => {
|
||||
if (this.props.newNoteAttachFileAction === AttachFileAction.AttachDrawing) {
|
||||
await this.drawPicture_onPress();
|
||||
} else {
|
||||
const options: AttachFileOptions = {
|
||||
action: this.props.newNoteAttachFileAction,
|
||||
};
|
||||
await CommandService.instance().execute('attachFile', '', options);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
@ -1294,6 +1309,11 @@ class NoteScreenComponent extends BaseScreenComponent<ComponentProps, State> imp
|
||||
done = true;
|
||||
}
|
||||
|
||||
if (!this.noteEditorVisible()) {
|
||||
logger.info(`Note editor is not visible - not setting focus on ${fieldToFocus}`);
|
||||
done = true;
|
||||
}
|
||||
|
||||
if (done) {
|
||||
shim.clearInterval(this.focusUpdateIID_);
|
||||
this.focusUpdateIID_ = null;
|
||||
@ -1375,6 +1395,10 @@ class NoteScreenComponent extends BaseScreenComponent<ComponentProps, State> imp
|
||||
this.setState({ voiceTypingDialogShown: false });
|
||||
}
|
||||
|
||||
private noteEditorVisible() {
|
||||
return !this.state.showCamera && !this.state.showImageEditor;
|
||||
}
|
||||
|
||||
public render() {
|
||||
// Commands must be registered before child components can render.
|
||||
// Calling this in the constructor won't work in strict mode, where
|
||||
@ -1611,6 +1635,7 @@ const NoteScreen = connect((state: AppState) => {
|
||||
return {
|
||||
noteId: state.selectedNoteIds.length ? state.selectedNoteIds[0] : null,
|
||||
noteHash: state.selectedNoteHash,
|
||||
newNoteAttachFileAction: state.newNoteAttachFileAction,
|
||||
itemType: state.selectedItemType,
|
||||
folders: state.folders,
|
||||
searchQuery: state.searchQuery,
|
||||
|
@ -8,6 +8,17 @@ import Logger from '@joplin/utils/Logger';
|
||||
|
||||
const logger = Logger.create('attachFile');
|
||||
|
||||
export enum AttachFileAction {
|
||||
TakePhoto = 'takePhoto',
|
||||
AttachFile = 'attachFile',
|
||||
AttachPhoto = 'attachPhoto',
|
||||
AttachDrawing = 'attachDrawing',
|
||||
}
|
||||
|
||||
export interface AttachFileOptions {
|
||||
action?: AttachFileAction | null;
|
||||
}
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'attachFile',
|
||||
label: () => _('Attach file'),
|
||||
@ -50,35 +61,46 @@ export const runtime = (props: CommandRuntimeProps): CommandRuntime => {
|
||||
}
|
||||
};
|
||||
|
||||
const showAttachMenu = async () => {
|
||||
const showAttachMenu = async (action: AttachFileAction = null) => {
|
||||
props.hideKeyboard();
|
||||
|
||||
const buttons = [];
|
||||
let buttonId: AttachFileAction = null;
|
||||
|
||||
// On iOS, it will show "local files", which means certain files saved from the browser
|
||||
// and the iCloud files, but it doesn't include photos and images from the CameraRoll
|
||||
//
|
||||
// On Android, it will depend on the phone, but usually it will allow browsing all files and photos.
|
||||
buttons.push({ text: _('Attach file'), id: 'attachFile' });
|
||||
if (action) {
|
||||
buttonId = action;
|
||||
} else {
|
||||
const buttons = [];
|
||||
|
||||
// Disabled on Android because it doesn't work due to permission issues, but enabled on iOS
|
||||
// because that's only way to browse photos from the camera roll.
|
||||
if (Platform.OS === 'ios') buttons.push({ text: _('Attach photo'), id: 'attachPhoto' });
|
||||
buttons.push({ text: _('Take photo'), id: 'takePhoto' });
|
||||
// On iOS, it will show "local files", which means certain files saved from the browser
|
||||
// and the iCloud files, but it doesn't include photos and images from the CameraRoll
|
||||
//
|
||||
// On Android, it will depend on the phone, but usually it will allow browsing all files and photos.
|
||||
buttons.push({ text: _('Attach file'), id: AttachFileAction.AttachFile });
|
||||
|
||||
const buttonId = await props.dialogs.showMenu(_('Choose an option'), buttons);
|
||||
// Disabled on Android because it doesn't work due to permission issues, but enabled on iOS
|
||||
// because that's only way to browse photos from the camera roll.
|
||||
if (Platform.OS === 'ios') buttons.push({ text: _('Attach photo'), id: AttachFileAction.AttachPhoto });
|
||||
buttons.push({ text: _('Take photo'), id: AttachFileAction.TakePhoto });
|
||||
|
||||
if (buttonId === 'takePhoto') await takePhoto();
|
||||
if (buttonId === 'attachFile') await attachFile();
|
||||
if (buttonId === 'attachPhoto') await attachPhoto();
|
||||
buttonId = await props.dialogs.showMenu(_('Choose an option'), buttons) as AttachFileAction;
|
||||
}
|
||||
|
||||
if (buttonId === AttachFileAction.TakePhoto) await takePhoto();
|
||||
if (buttonId === AttachFileAction.AttachFile) await attachFile();
|
||||
if (buttonId === AttachFileAction.AttachPhoto) await attachPhoto();
|
||||
};
|
||||
|
||||
return {
|
||||
execute: async (_context: CommandContext, filePath?: string) => {
|
||||
execute: async (_context: CommandContext, filePath?: string, options: AttachFileOptions = null) => {
|
||||
options = {
|
||||
action: null,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (filePath) {
|
||||
await props.attachFile({ uri: filePath }, 'all');
|
||||
} else {
|
||||
await showAttachMenu();
|
||||
await showAttachMenu(options.action);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -354,6 +354,10 @@ const appReducer = (state = appDefaultState, action: any) => {
|
||||
newState.selectedNoteHash = action.noteHash;
|
||||
}
|
||||
|
||||
if ('newNoteAttachFileAction' in action) {
|
||||
newState.newNoteAttachFileAction = action.newNoteAttachFileAction;
|
||||
}
|
||||
|
||||
if ('sharedData' in action) {
|
||||
newState.sharedData = action.sharedData;
|
||||
} else {
|
||||
|
@ -4,6 +4,8 @@ import { Dispatch } from 'redux';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import { DeviceEventEmitter } from 'react-native';
|
||||
import { GotoNoteOptions } from './commands/util/goToNote';
|
||||
import { AttachFileAction } from './components/screens/Note/commands/attachFile';
|
||||
|
||||
const logger = Logger.create('setupQuickActions');
|
||||
|
||||
@ -19,9 +21,17 @@ export default async (dispatch: Dispatch) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
// List of iOS icons:
|
||||
// https://github.com/EvanBacon/expo-quick-actions?tab=readme-ov-file#system-icons
|
||||
//
|
||||
// Note: on Android, anything beyond the fourth menu item appears to be ignored, at least on
|
||||
// emulator.
|
||||
QuickActions.setShortcutItems([
|
||||
{ type: 'New note', title: _('New note'), icon: 'Compose', userInfo },
|
||||
{ type: 'New to-do', title: _('New to-do'), icon: 'Add', userInfo },
|
||||
{ type: 'newNote', title: _('New note'), icon: 'Compose', userInfo },
|
||||
{ type: 'newTodo', title: _('New to-do'), icon: 'Add', userInfo },
|
||||
{ type: 'newPhoto', title: _('New photo'), icon: 'CapturePhoto', userInfo },
|
||||
{ type: 'newResource', title: _('New attachment'), icon: 'Bookmark', userInfo },
|
||||
{ type: 'newDrawing', title: _('New drawing'), icon: 'Favorite', userInfo },
|
||||
]);
|
||||
|
||||
try {
|
||||
@ -50,6 +60,18 @@ const quickActionHandler = (dispatch: Dispatch) => async (data: TData) => {
|
||||
dispatch({ type: 'NAV_BACK' });
|
||||
dispatch({ type: 'SIDE_MENU_CLOSE' });
|
||||
|
||||
const isTodo = data.type === 'New to-do' ? 1 : 0;
|
||||
await CommandService.instance().execute('newNote', '', isTodo);
|
||||
const isTodo = data.type === 'newTodo' ? 1 : 0;
|
||||
const options: GotoNoteOptions = {
|
||||
attachFileAction: null,
|
||||
};
|
||||
|
||||
if (data.type === 'newPhoto') {
|
||||
options.attachFileAction = AttachFileAction.TakePhoto;
|
||||
} else if (data.type === 'newResource') {
|
||||
options.attachFileAction = AttachFileAction.AttachFile;
|
||||
} else if (data.type === 'newDrawing') {
|
||||
options.attachFileAction = AttachFileAction.AttachDrawing;
|
||||
}
|
||||
|
||||
await CommandService.instance().execute('newNote', '', isTodo, options);
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { defaultState } from '@joplin/lib/reducer';
|
||||
import { AppState } from './types';
|
||||
|
||||
|
||||
export const DEFAULT_ROUTE = {
|
||||
type: 'NAV_GO',
|
||||
routeName: 'Notes',
|
||||
@ -10,7 +9,6 @@ export const DEFAULT_ROUTE = {
|
||||
|
||||
const appDefaultState: AppState = {
|
||||
smartFilterId: undefined,
|
||||
...defaultState,
|
||||
keyboardVisible: false,
|
||||
route: DEFAULT_ROUTE,
|
||||
noteSelectionEnabled: false,
|
||||
@ -18,5 +16,7 @@ const appDefaultState: AppState = {
|
||||
isOnMobileData: false,
|
||||
disableSideMenuGestures: false,
|
||||
showPanelsDialog: false,
|
||||
newNoteAttachFileAction: null,
|
||||
...defaultState,
|
||||
};
|
||||
export default appDefaultState;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { State } from '@joplin/lib/reducer';
|
||||
import { AttachFileAction } from '../components/screens/Note/commands/attachFile';
|
||||
|
||||
export interface AppState extends State {
|
||||
showPanelsDialog: boolean;
|
||||
@ -10,4 +11,6 @@ export interface AppState extends State {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
noteSideMenuOptions: any;
|
||||
disableSideMenuGestures: boolean;
|
||||
|
||||
newNoteAttachFileAction: AttachFileAction | null;
|
||||
}
|
||||
|
@ -147,5 +147,6 @@ setsize
|
||||
Comprar
|
||||
seguidores
|
||||
devbox
|
||||
tablist
|
||||
Ökonomie
|
||||
Favorite
|
||||
tablist
|
||||
|
Loading…
Reference in New Issue
Block a user