You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Resize images
This commit is contained in:
		| @@ -14,6 +14,8 @@ msgstr "" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "X-Generator: Poedit 2.0.3\n" | ||||
| "POT-Creation-Date: \n" | ||||
| "PO-Revision-Date: \n" | ||||
|  | ||||
| msgid "No notebook selected." | ||||
| msgstr "Aucun carnet n'est sélectionné." | ||||
| @@ -577,7 +579,7 @@ msgstr "" | ||||
| "(+)." | ||||
|  | ||||
| msgid "Welcome" | ||||
| msgstr "Bienvenu" | ||||
| msgstr "Bienvenue" | ||||
|  | ||||
| #~ msgid "NAME" | ||||
| #~ msgstr "NOM" | ||||
|   | ||||
| @@ -137,6 +137,7 @@ android { | ||||
| } | ||||
|  | ||||
| dependencies { | ||||
|     compile project(':react-native-image-resizer') | ||||
| 	compile project(':react-native-fs') | ||||
| 	compile fileTree(dir: "libs", include: ["*.jar"]) | ||||
| 	compile "com.android.support:appcompat-v7:23.0.1" | ||||
| @@ -144,6 +145,7 @@ dependencies { | ||||
| 	compile project(':react-native-sqlite-storage') | ||||
| 	compile project(':react-native-fetch-blob') | ||||
| 	compile project(':react-native-document-picker') | ||||
| 	compile project(':react-native-image-resizer') | ||||
| } | ||||
|  | ||||
| // Run this once to be able to run the application with BUCK | ||||
|   | ||||
| @@ -11,6 +11,7 @@ import com.facebook.soloader.SoLoader; | ||||
| import org.pgsqlite.SQLitePluginPackage; | ||||
| import com.RNFetchBlob.RNFetchBlobPackage; | ||||
| import com.reactnativedocumentpicker.ReactNativeDocumentPicker; | ||||
| import fr.bamlab.rnimageresizer.ImageResizerPackage; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| @@ -30,7 +31,8 @@ public class MainApplication extends Application implements ReactApplication { | ||||
| 				new MainReactPackage(), | ||||
| 				new RNFSPackage(), | ||||
| 				new RNFetchBlobPackage(), | ||||
| 				new ReactNativeDocumentPicker() | ||||
| 				new ReactNativeDocumentPicker(), | ||||
| 				new ImageResizerPackage() | ||||
| 			); | ||||
| 		} | ||||
| 	}; | ||||
| @@ -1,4 +1,6 @@ | ||||
| rootProject.name = 'Joplin' | ||||
| include ':react-native-image-resizer' | ||||
| project(':react-native-image-resizer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-resizer/android') | ||||
| include ':react-native-fs' | ||||
| project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android') | ||||
|  | ||||
|   | ||||
| @@ -36,6 +36,7 @@ | ||||
| 		5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; | ||||
| 		832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; | ||||
| 		EA51DDC9EBFC469F8214B3AD /* libRNFS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8E646D13B9444DE81EC441D /* libRNFS.a */; }; | ||||
| 		628436ED66784ABE86A775AE /* libRCTImageResizer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B8E2583D2B6447DB35F295C /* libRCTImageResizer.a */; }; | ||||
| /* End PBXBuildFile section */ | ||||
|  | ||||
| /* Begin PBXContainerItemProxy section */ | ||||
| @@ -257,6 +258,8 @@ | ||||
| 		832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; }; | ||||
| 		8C2AA97067234408AD5BFD90 /* RNFS.xcodeproj */ = {isa = PBXFileReference; name = "RNFS.xcodeproj"; path = "../node_modules/react-native-fs/RNFS.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; | ||||
| 		A8E646D13B9444DE81EC441D /* libRNFS.a */ = {isa = PBXFileReference; name = "libRNFS.a"; path = "libRNFS.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; | ||||
| 		8FB22B82988847ED8E7C0976 /* RCTImageResizer.xcodeproj */ = {isa = PBXFileReference; name = "RCTImageResizer.xcodeproj"; path = "../node_modules/react-native-image-resizer/ios/RCTImageResizer.xcodeproj"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; | ||||
| 		9B8E2583D2B6447DB35F295C /* libRCTImageResizer.a */ = {isa = PBXFileReference; name = "libRCTImageResizer.a"; path = "libRCTImageResizer.a"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; | ||||
| /* End PBXFileReference section */ | ||||
|  | ||||
| /* Begin PBXFrameworksBuildPhase section */ | ||||
| @@ -284,6 +287,7 @@ | ||||
| 				00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, | ||||
| 				139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, | ||||
| 				EA51DDC9EBFC469F8214B3AD /* libRNFS.a in Frameworks */, | ||||
| 				628436ED66784ABE86A775AE /* libRCTImageResizer.a in Frameworks */, | ||||
| 			); | ||||
| 			runOnlyForDeploymentPostprocessing = 0; | ||||
| 		}; | ||||
| @@ -451,6 +455,7 @@ | ||||
| 				00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, | ||||
| 				139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, | ||||
| 				8C2AA97067234408AD5BFD90 /* RNFS.xcodeproj */, | ||||
| 				8FB22B82988847ED8E7C0976 /* RCTImageResizer.xcodeproj */, | ||||
| 			); | ||||
| 			name = Libraries; | ||||
| 			sourceTree = "<group>"; | ||||
| @@ -979,10 +984,12 @@ | ||||
| 				LIBRARY_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 				); | ||||
| 				HEADER_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"$(SRCROOT)/../node_modules/react-native-fs/**", | ||||
| 					"$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", | ||||
| 				); | ||||
| 			}; | ||||
| 			name = Debug; | ||||
| @@ -1004,10 +1011,12 @@ | ||||
| 				LIBRARY_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 				); | ||||
| 				HEADER_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"$(SRCROOT)/../node_modules/react-native-fs/**", | ||||
| 					"$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", | ||||
| 				); | ||||
| 			}; | ||||
| 			name = Release; | ||||
| @@ -1030,6 +1039,7 @@ | ||||
| 				HEADER_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"$(SRCROOT)/../node_modules/react-native-fs/**", | ||||
| 					"$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", | ||||
| 				); | ||||
| 			}; | ||||
| 			name = Debug; | ||||
| @@ -1051,6 +1061,7 @@ | ||||
| 				HEADER_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"$(SRCROOT)/../node_modules/react-native-fs/**", | ||||
| 					"$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", | ||||
| 				); | ||||
| 			}; | ||||
| 			name = Release; | ||||
| @@ -1081,10 +1092,12 @@ | ||||
| 				LIBRARY_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 				); | ||||
| 				HEADER_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"$(SRCROOT)/../node_modules/react-native-fs/**", | ||||
| 					"$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", | ||||
| 				); | ||||
| 			}; | ||||
| 			name = Debug; | ||||
| @@ -1115,10 +1128,12 @@ | ||||
| 				LIBRARY_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 				); | ||||
| 				HEADER_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"$(SRCROOT)/../node_modules/react-native-fs/**", | ||||
| 					"$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", | ||||
| 				); | ||||
| 			}; | ||||
| 			name = Release; | ||||
| @@ -1144,6 +1159,7 @@ | ||||
| 				LIBRARY_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 				); | ||||
| 			}; | ||||
| 			name = Debug; | ||||
| @@ -1169,6 +1185,7 @@ | ||||
| 				LIBRARY_SEARCH_PATHS = ( | ||||
| 					"$(inherited)", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 					"\"$(SRCROOT)/$(TARGET_NAME)\"", | ||||
| 				); | ||||
| 			}; | ||||
| 			name = Release; | ||||
|   | ||||
| @@ -129,7 +129,7 @@ class NoteBodyViewer extends Component { | ||||
| 			const mime = r.mime.toLowerCase(); | ||||
| 			if (mime == 'image/png' || mime == 'image/jpg' || mime == 'image/jpeg' || mime == 'image/gif') { | ||||
| 				const src = 'data:' + r.mime + ';base64,' + r.base64; | ||||
| 				let output = '<img title="' + htmlentities(title) + '" src="' + htmlentities(src) + '"/>'; | ||||
| 				let output = '<img title="' + htmlentities(title) + '" src="' + src + '"/>'; | ||||
| 				return output; | ||||
| 			} | ||||
| 			 | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import React, { Component } from 'react'; | ||||
| import { BackHandler, View, Button, TextInput, WebView, Text, StyleSheet, Linking } from 'react-native'; | ||||
| import { BackHandler, View, Button, TextInput, WebView, Text, StyleSheet, Linking, Image } from 'react-native'; | ||||
| import { connect } from 'react-redux' | ||||
| import { uuid } from 'lib/uuid.js'; | ||||
| import { Log } from 'lib/log.js' | ||||
| @@ -22,7 +22,7 @@ import DialogBox from 'react-native-dialogbox'; | ||||
| import { NoteBodyViewer } from 'lib/components/note-body-viewer.js'; | ||||
| import RNFetchBlob from 'react-native-fetch-blob'; | ||||
| import { DocumentPicker, DocumentPickerUtil } from 'react-native-document-picker'; | ||||
|  | ||||
| import ImageResizer from 'react-native-image-resizer'; | ||||
|  | ||||
| class NoteScreenComponent extends BaseScreenComponent { | ||||
| 	 | ||||
| @@ -100,6 +100,11 @@ class NoteScreenComponent extends BaseScreenComponent { | ||||
| 				paddingTop: theme.marginTop, | ||||
| 				paddingBottom: theme.marginBottom, | ||||
| 			}, | ||||
| 			metadata: { | ||||
| 				paddingLeft: globalStyle.marginLeft, | ||||
| 				paddingRight: globalStyle.marginRight, | ||||
| 				color: theme.color, | ||||
| 			}, | ||||
| 		}; | ||||
|  | ||||
| 		styles.titleContainer = { | ||||
| @@ -264,9 +269,22 @@ class NoteScreenComponent extends BaseScreenComponent { | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	async imageDimensions(uri) { | ||||
| 		return new Promise((resolve, reject) => { | ||||
| 			Image.getSize(uri, (width, height) => { | ||||
| 				resolve({ width: width, height: height }); | ||||
| 			}, (error) => { reject(error) }); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	async attachFile_onPress() { | ||||
| 		const res = await this.pickDocument(); | ||||
|  | ||||
| 		const localFilePath = res.uri; | ||||
|  | ||||
| 		reg.logger().info('Got file: ' + localFilePath); | ||||
| 		reg.logger().info('Got type: ' + res.type); | ||||
|  | ||||
| 		// res.uri, | ||||
| 		// res.type, // mime type | ||||
| 		// res.fileName, | ||||
| @@ -277,16 +295,42 @@ class NoteScreenComponent extends BaseScreenComponent { | ||||
| 		resource.mime = res.type; | ||||
| 		resource.title = res.fileName ? res.fileName : _('Untitled'); | ||||
|  | ||||
| 		const targetPath = Resource.fullPath(resource); | ||||
| 		RNFetchBlob.fs.cp(res.uri, targetPath); | ||||
| 		let targetPath = Resource.fullPath(resource); | ||||
|  | ||||
| 		if (res.type == 'image/jpeg' || res.type == 'image/jpg' || res.type == 'image/png') { | ||||
| 			const maxSize = 1920; | ||||
|  | ||||
| 			let dimensions = await this.imageDimensions(localFilePath); | ||||
|  | ||||
| 			reg.logger().info('Original dimensions ', dimensions); | ||||
| 			if (dimensions.width > maxSize || dimensions.height > maxSize) { | ||||
| 				dimensions.width = maxSize; | ||||
| 				dimensions.height = maxSize; | ||||
| 			} | ||||
| 			reg.logger().info('New dimensions ', dimensions); | ||||
|  | ||||
| 			const format = res.type == 'image/png' ? 'PNG' : 'JPEG'; | ||||
| 			reg.logger().info('Resizing image ' + localFilePath); | ||||
| 			const resizedImagePath = await ImageResizer.createResizedImage(localFilePath, dimensions.width, dimensions.height, format, 85); | ||||
| 			reg.logger().info('Resized image ', resizedImagePath); | ||||
| 			RNFetchBlob.fs.cp(resizedImagePath, targetPath); // mv doesn't work ("source path does not exist") so need to do cp and unlink | ||||
| 			 | ||||
| 			try { | ||||
| 				RNFetchBlob.fs.unlink(resizedImagePath); | ||||
| 			} catch (error) { | ||||
| 				reg.logger().info('Error when unlinking cached file: ', error); | ||||
| 			} | ||||
| 		} else { | ||||
| 			RNFetchBlob.fs.cp(localFilePath, targetPath); | ||||
| 		} | ||||
|  | ||||
| 		await Resource.save(resource, { isNew: true }); | ||||
|  | ||||
| 		const resourceTag = Resource.markdownTag(resource); | ||||
|  | ||||
| 			const newNote = Object.assign({}, this.state.note); | ||||
| 			newNote.body += "\n" + resourceTag; | ||||
| 			this.setState({ note: newNote }); | ||||
| 		const newNote = Object.assign({}, this.state.note); | ||||
| 		newNote.body += "\n" + resourceTag; | ||||
| 		this.setState({ note: newNote }); | ||||
| 	} | ||||
|  | ||||
| 	toggleIsTodo_onPress() { | ||||
| @@ -467,7 +511,7 @@ class NoteScreenComponent extends BaseScreenComponent { | ||||
| 				{ titleComp } | ||||
| 				{ bodyComponent } | ||||
| 				{ actionButtonComp } | ||||
| 				{ this.state.showNoteMetadata && <Text style={{ paddingLeft: globalStyle.marginLeft, paddingRight: globalStyle.marginRight, }}>{this.state.noteMetadata}</Text> } | ||||
| 				{ this.state.showNoteMetadata && <Text style={this.styles().metadata}>{this.state.noteMetadata}</Text> } | ||||
| 				<DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/> | ||||
| 			</View> | ||||
| 		); | ||||
|   | ||||
							
								
								
									
										16
									
								
								ReactNativeClient/lib/markdown-utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								ReactNativeClient/lib/markdown-utils.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| const markdownUtils = { | ||||
|  | ||||
| 	// Not really escaping because that's not supported by marked.js | ||||
| 	escapeLinkText(text) { | ||||
| 		return text.replace(/(\[|\]|\(|\))/g, '_'); | ||||
| 	}, | ||||
|  | ||||
| 	escapeLinkUrl(url) { | ||||
| 		url = url.replace(/\(/g, '%28'); | ||||
| 		url = url.replace(/\)/g, '%29'); | ||||
| 		return url; | ||||
| 	}, | ||||
|  | ||||
| }; | ||||
|  | ||||
| export { markdownUtils }; | ||||
| @@ -4,6 +4,7 @@ import { Setting } from 'lib/models/setting.js'; | ||||
| import { mime } from 'lib/mime-utils.js'; | ||||
| import { filename } from 'lib/path-utils.js'; | ||||
| import { FsDriverDummy } from 'lib/fs-driver-dummy.js'; | ||||
| import { markdownUtils } from 'lib/markdown-utils.js'; | ||||
| import lodash  from 'lodash'; | ||||
|  | ||||
| class Resource extends BaseItem { | ||||
| @@ -44,11 +45,11 @@ class Resource extends BaseItem { | ||||
| 		let lines = []; | ||||
| 		if (Resource.isSupportedImageMimeType(resource.mime)) { | ||||
| 			lines.push(""); | ||||
| 		} else { | ||||
| 			lines.push("["); | ||||
| 			lines.push(tagAlt); | ||||
| 			lines.push(markdownUtils.escapeLinkText(tagAlt)); | ||||
| 			lines.push("](:/" + resource.id + ")"); | ||||
| 		} | ||||
| 		return lines.join(''); | ||||
|   | ||||
| @@ -56,7 +56,7 @@ class Synchronizer { | ||||
| 		if (report.updateRemote) lines.push(_('Updated remote items: %d.', report.updateRemote)); | ||||
| 		if (report.deleteLocal) lines.push(_('Deleted local items: %d.', report.deleteLocal)); | ||||
| 		if (report.deleteRemote) lines.push(_('Deleted remote items: %d.', report.deleteRemote)); | ||||
| 		if (!report.completedTime && report.state) lines.push(_('State: %s.', report.state.replace(/_/g, ' '))); | ||||
| 		if (!report.completedTime && report.state) lines.push(_('State: "%s".', report.state)); | ||||
| 		if (report.errors && report.errors.length) lines.push(_('Last error: %s (stacktrace in log).', report.errors[report.errors.length-1].message)); | ||||
| 		if (report.cancelling && !report.completedTime) lines.push(_('Cancelling...')); | ||||
| 		if (report.completedTime) lines.push(_('Completed: %s', time.unixMsToLocalDateTime(report.completedTime))); | ||||
|   | ||||
| @@ -20,6 +20,7 @@ | ||||
|     "react-native-document-picker": "^2.0.0", | ||||
|     "react-native-fetch-blob": "^0.10.6", | ||||
|     "react-native-fs": "^2.3.3", | ||||
|     "react-native-image-resizer": "^0.1.1", | ||||
|     "react-native-popup-menu": "^0.7.4", | ||||
|     "react-native-side-menu": "^0.20.1", | ||||
|     "react-native-sqlite-storage": "3.3.*", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user