1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-11-26 22:41:17 +02:00

Android: Resolves #2896: Enable sharing to Joplin on Android (#2870)

This commit is contained in:
Roman Musin
2020-06-04 18:40:44 +01:00
committed by GitHub
parent 949c92f6d6
commit 33ad0dce15
13 changed files with 324 additions and 99 deletions

View File

@@ -0,0 +1,19 @@
const { NativeModules, Platform } = require('react-native');
export interface SharedData {
title?: string,
text?: string,
resources?: string[]
}
const ShareExtension = (Platform.OS === 'android' && NativeModules.ShareExtension) ?
{
data: () => NativeModules.ShareExtension.data(),
close: () => NativeModules.ShareExtension.close(),
} :
{
data: () => {},
close: () => {},
};
export default ShareExtension;

View File

@@ -0,0 +1,9 @@
const { PermissionsAndroid } = require('react-native');
export default async (permissions: string) => {
let result = await PermissionsAndroid.check(permissions);
if (result !== PermissionsAndroid.RESULTS.GRANTED) {
result = await PermissionsAndroid.request(permissions);
}
return result === PermissionsAndroid.RESULTS.GRANTED;
};

View File

@@ -36,7 +36,7 @@ const ImageResizer = require('react-native-image-resizer').default;
const shared = require('lib/components/shared/note-screen-shared.js');
const ImagePicker = require('react-native-image-picker');
const { SelectDateTimeDialog } = require('lib/components/select-date-time-dialog.js');
// const ShareExtension = require('react-native-share-extension').default;
const ShareExtension = require('lib/ShareExtension.js').default;
const CameraView = require('lib/components/CameraView');
const SearchEngine = require('lib/services/SearchEngine');
const urlUtils = require('lib/urlUtils');
@@ -123,6 +123,19 @@ class NoteScreenComponent extends BaseScreenComponent {
return true;
}
if (this.state.fromShare) {
// effectively the same as NAV_BACK but NAV_BACK causes undesired behaviour in this case:
// - share to Joplin from some other app
// - open Joplin and open any note
// - go back -- with NAV_BACK this causes the app to exit rather than just showing notes
this.props.dispatch({
type: 'NAV_GO',
routeName: 'Notes',
folderId: this.state.note.parent_id,
});
return true;
}
return false;
};
@@ -333,9 +346,9 @@ class NoteScreenComponent extends BaseScreenComponent {
shared.uninstallResourceHandling(this.refreshResource);
// if (Platform.OS !== 'ios' && this.state.fromShare) {
// ShareExtension.close();
// }
if (this.state.fromShare) {
ShareExtension.close();
}
}
title_changeText(text) {
@@ -527,7 +540,7 @@ class NoteScreenComponent extends BaseScreenComponent {
try {
if (mimeType == 'image/jpeg' || mimeType == 'image/jpg' || mimeType == 'image/png') {
const done = await this.resizeImage(localFilePath, targetPath, pickerResponse.mime);
const done = await this.resizeImage(localFilePath, targetPath, mimeType);
if (!done) return;
} else {
if (fileType === 'image') {

View File

@@ -200,8 +200,7 @@ shared.initState = async function(comp) {
const note = await Note.load(comp.props.noteId);
let mode = 'view';
if (isProvisionalNote) {
// note = comp.props.itemType == 'todo' ? Note.newTodo(comp.props.folderId) : Note.new(comp.props.folderId);
if (isProvisionalNote && !comp.props.sharedData) {
mode = 'edit';
comp.scheduleFocusUpdate();
}
@@ -218,8 +217,25 @@ shared.initState = async function(comp) {
noteResources: await shared.attachedResources(note ? note.body : ''),
});
if (comp.props.sharedData) {
this.noteComponent_change(comp, 'body', comp.props.sharedData.value);
if (comp.props.sharedData.title) {
this.noteComponent_change(comp, 'title', comp.props.sharedData.title);
}
if (comp.props.sharedData.text) {
this.noteComponent_change(comp, 'body', comp.props.sharedData.text);
}
if (comp.props.sharedData.resources) {
for (let i = 0; i < comp.props.sharedData.resources.length; i++) {
const resource = comp.props.sharedData.resources[i];
reg.logger().info(`about to attach resource ${JSON.stringify(resource)}`);
await comp.attachFile({
uri: resource.uri,
type: resource.mimeType,
fileName: resource.name,
}, null);
}
}
}
// eslint-disable-next-line require-atomic-updates

View File

@@ -0,0 +1,42 @@
const Note = require('lib/models/Note.js');
const checkPermissions = require('lib/checkPermissions.js').default;
const { ToastAndroid } = require('react-native');
const { PermissionsAndroid } = require('react-native');
import ShareExtension, { SharedData } from './ShareExtension';
export default async (sharedData: SharedData, folderId: string, dispatch: Function) => {
if (!!sharedData.resources && sharedData.resources.length > 0) {
const hasPermissions = await checkPermissions(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE);
if (!hasPermissions) {
ToastAndroid.show('Cannot receive shared data - permission denied', ToastAndroid.SHORT);
ShareExtension.close();
return;
}
}
// This is a bit hacky, but the surest way to go to
// the needed note. We go back one screen in case there's
// already a note open - if we don't do this, the dispatch
// below will do nothing (because routeName wouldn't change)
// Then we wait a bit for the state to be set correctly, and
// finally we go to the new note.
await dispatch({ type: 'NAV_BACK' });
await dispatch({ type: 'SIDE_MENU_CLOSE' });
const newNote = await Note.save({
parent_id: folderId,
}, { provisional: true });
setTimeout(() => {
dispatch({
type: 'NAV_GO',
routeName: 'Note',
noteId: newNote.id,
sharedData: sharedData,
});
}, 5);
};