You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Prompt dialog and popup menu
This commit is contained in:
		| @@ -2,6 +2,7 @@ const { _ } = require('lib/locale.js'); | ||||
| const { BrowserWindow } = require('electron'); | ||||
| const url = require('url') | ||||
| const path = require('path') | ||||
| const urlUtils = require('lib/urlUtils.js'); | ||||
|  | ||||
| class ElectronAppWrapper { | ||||
|  | ||||
| @@ -27,20 +28,6 @@ class ElectronAppWrapper { | ||||
| 		return this.win_; | ||||
| 	} | ||||
|  | ||||
| 	// store() { | ||||
| 	// 	return this.store_; | ||||
| 	// } | ||||
|  | ||||
| 	// dispatch(action) { | ||||
| 	// 	return this.store().dispatch(action); | ||||
| 	// } | ||||
|  | ||||
| 	// windowContentSize() { | ||||
| 	// 	if (!this.win_) return { width: 0, height: 0 }; | ||||
| 	// 	const s = this.win_.getContentSize(); | ||||
| 	// 	return { width: s[0], height: s[1] }; | ||||
| 	// } | ||||
|  | ||||
| 	createWindow() { | ||||
| 		this.win_ = new BrowserWindow({width: 800, height: 600}) | ||||
|  | ||||
| @@ -55,18 +42,6 @@ class ElectronAppWrapper { | ||||
| 		this.win_.on('closed', () => { | ||||
| 			this.win_ = null | ||||
| 		}) | ||||
|  | ||||
| 		this.win_.on('resize', () => { | ||||
| 			// this.dispatch({ | ||||
| 			// 	type: 'WINDOW_CONTENT_SIZE_SET', | ||||
| 			// 	size: this.windowContentSize(), | ||||
| 			// }); | ||||
| 		}); | ||||
|  | ||||
| 		// this.dispatch({ | ||||
| 		// 	type: 'WINDOW_CONTENT_SIZE_SET', | ||||
| 		// 	size: this.windowContentSize(), | ||||
| 		// }); | ||||
| 	} | ||||
|  | ||||
| 	async waitForElectronAppReady() { | ||||
|   | ||||
| @@ -1,3 +1,5 @@ | ||||
| const { _ } = require('lib/locale.js'); | ||||
|  | ||||
| class Bridge { | ||||
|  | ||||
| 	constructor(electronWrapper) { | ||||
| @@ -23,6 +25,30 @@ class Bridge { | ||||
| 		return dialog.showMessageBox(options); | ||||
| 	} | ||||
|  | ||||
| 	showErrorMessageBox(message) { | ||||
| 		return this.showMessageBox({ | ||||
| 			type: 'error', | ||||
| 			message: message, | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	showConfirmMessageBox(message) { | ||||
| 		const result = this.showMessageBox({ | ||||
| 			type: 'question', | ||||
| 			message: message, | ||||
| 			buttons: [_('OK'), _('Cancel')], | ||||
| 		}); | ||||
| 		return result === 0; | ||||
| 	} | ||||
|  | ||||
| 	get Menu() { | ||||
| 		return require('electron').Menu; | ||||
| 	} | ||||
|  | ||||
| 	get MenuItem() { | ||||
| 		return require('electron').MenuItem; | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| let bridge_ = null; | ||||
|   | ||||
| @@ -11,7 +11,6 @@ class HeaderComponent extends React.Component { | ||||
| 	} | ||||
|  | ||||
| 	makeButton(key, options) { | ||||
| 		console.info(key, options); | ||||
| 		return <a key={key} href="#" onClick={() => {options.onClick()}}>{options.title}</a> | ||||
| 	} | ||||
|  | ||||
| @@ -42,7 +41,7 @@ class HeaderComponent extends React.Component { | ||||
| } | ||||
|  | ||||
| const mapStateToProps = (state) => { | ||||
| 	return { theme: state.theme }; | ||||
| 	return { theme: state.settings.theme }; | ||||
| }; | ||||
|  | ||||
| const Header = connect(mapStateToProps)(HeaderComponent); | ||||
|   | ||||
| @@ -4,11 +4,20 @@ const { Header } = require('./Header.min.js'); | ||||
| const { SideBar } = require('./SideBar.min.js'); | ||||
| const { NoteList } = require('./NoteList.min.js'); | ||||
| const { NoteText } = require('./NoteText.min.js'); | ||||
| const { PromptDialog } = require('./PromptDialog.min.js'); | ||||
| const { Setting } = require('lib/models/setting.js'); | ||||
| const { Note } = require('lib/models/note.js'); | ||||
| const { themeStyle } = require('../theme.js'); | ||||
| const { _ } = require('lib/locale.js'); | ||||
| const layoutUtils = require('lib/layout-utils.js'); | ||||
| const { bridge } = require('electron').remote.require('./bridge'); | ||||
|  | ||||
| class MainScreenComponent extends React.Component { | ||||
|  | ||||
| 	componentWillMount() { | ||||
| 		this.setState({ newNotePromptVisible: false }); | ||||
| 	} | ||||
|  | ||||
| 	render() { | ||||
| 		const style = this.props.style; | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
| @@ -40,9 +49,40 @@ class MainScreenComponent extends React.Component { | ||||
| 			verticalAlign: 'top', | ||||
| 		}; | ||||
|  | ||||
| 		const promptStyle = { | ||||
| 			width: style.width, | ||||
| 			height: style.height, | ||||
| 		}; | ||||
|  | ||||
| 		const headerButtons = [ | ||||
| 			{ | ||||
| 				title: _('New note'), | ||||
| 				onClick: () => { | ||||
| 					this.setState({ newNotePromptVisible: true }); | ||||
| 				}, | ||||
| 			}, | ||||
| 		]; | ||||
|  | ||||
| 		const newNotePromptOnAccept = async (answer) => { | ||||
| 			const folderId = Setting.value('activeFolderId'); | ||||
| 			if (!folderId) return; | ||||
|  | ||||
| 			const note = await Note.save({ | ||||
| 				title: answer, | ||||
| 				parent_id: folderId, | ||||
| 			}); | ||||
| 			Note.updateGeolocation(note.id); | ||||
|  | ||||
| 			this.props.dispatch({ | ||||
| 				type: 'NOTES_SELECT', | ||||
| 				noteId: note.id, | ||||
| 			}); | ||||
| 		} | ||||
|  | ||||
| 		return ( | ||||
| 			<div style={style}> | ||||
| 				<Header style={headerStyle} showBackButton={false} /> | ||||
| 				<PromptDialog style={promptStyle} onAccept={(answer) => newNotePromptOnAccept(answer)} message={_('Note title:')} visible={this.state.newNotePromptVisible}/> | ||||
| 				<Header style={headerStyle} showBackButton={false} buttons={headerButtons} /> | ||||
| 				<SideBar style={sideBarStyle} /> | ||||
| 				<NoteList itemHeight={40} style={noteListStyle} /> | ||||
| 				<NoteText style={noteTextStyle} /> | ||||
|   | ||||
| @@ -1,10 +1,28 @@ | ||||
| const { ItemList } = require('./ItemList.min.js'); | ||||
| const React = require('react'); | ||||
| const { connect } = require('react-redux'); | ||||
| const { themeStyle } = require('../theme.js'); | ||||
| const { _ } = require('lib/locale.js'); | ||||
| const { bridge } = require('electron').remote.require('./bridge'); | ||||
| const Menu = bridge().Menu; | ||||
| const MenuItem = bridge().MenuItem; | ||||
|  | ||||
| class NoteListComponent extends React.Component { | ||||
|  | ||||
| 	itemRenderer(index, item) { | ||||
| 	itemContextMenu(event) { | ||||
| 		const noteId = event.target.getAttribute('data-id'); | ||||
| 		if (!noteId) throw new Error('No data-id on element'); | ||||
|  | ||||
| 		const menu = new Menu() | ||||
| 		menu.append(new MenuItem({label: _('Delete'), async click() { | ||||
| 			const ok = bridge().showConfirmMessageBox(_('Delete note?')); | ||||
| 			if (!ok) return; | ||||
| 			await Note.delete(noteId); | ||||
| 		}})) | ||||
| 		menu.popup(bridge().window()); | ||||
| 	} | ||||
|  | ||||
| 	itemRenderer(index, item, theme) { | ||||
| 		const onClick = (item) => { | ||||
| 			this.props.dispatch({ | ||||
| 				type: 'NOTES_SELECT', | ||||
| @@ -12,20 +30,27 @@ class NoteListComponent extends React.Component { | ||||
| 			}); | ||||
| 		} | ||||
|  | ||||
| 		let classes = ['item']; | ||||
| 		classes.push(index % 2 === 0 ? 'even' : 'odd'); | ||||
| 		if (this.props.selectedNoteId === item.id) classes.push('selected'); | ||||
| 		return <div onClick={() => { onClick(item) }} className={classes.join(' ')} key={index}>{item.title + ' ' + item.id.substr(0,4)}</div> | ||||
| 		const style =  { | ||||
| 			height: this.props.itemHeight, | ||||
| 			display: 'block', | ||||
| 			cursor: 'pointer', | ||||
| 			backgroundColor: index % 2 === 0 ? theme.backgroundColor : theme.oddBackgroundColor, | ||||
| 			fontWeight: this.props.selectedNoteId === item.id ? 'bold' : 'normal', | ||||
| 		}; | ||||
|  | ||||
| 		return <a data-id={item.id} onContextMenu={(event) => this.itemContextMenu(event)} href="#" style={style} onClick={() => { onClick(item) }} key={index}>{item.title}</a> | ||||
| 	} | ||||
|  | ||||
| 	render() { | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
|  | ||||
| 		return ( | ||||
| 			<ItemList | ||||
| 				itemHeight={this.props.itemHeight} | ||||
| 				style={this.props.style} | ||||
| 				className={"note-list"} | ||||
| 				items={this.props.notes} | ||||
| 				itemRenderer={ (index, item) => { return this.itemRenderer(index, item) } } | ||||
| 				itemRenderer={ (index, item) => { return this.itemRenderer(index, item, theme) } } | ||||
| 			></ItemList> | ||||
| 		); | ||||
| 	} | ||||
| @@ -36,6 +61,7 @@ const mapStateToProps = (state) => { | ||||
| 	return { | ||||
| 		notes: state.notes, | ||||
| 		selectedNoteId: state.selectedNoteId, | ||||
| 		theme: state.settings.theme, | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ const { reg } = require('lib/registry.js'); | ||||
| const MdToHtml = require('lib/MdToHtml'); | ||||
| const shared = require('lib/components/shared/note-screen-shared.js'); | ||||
| const { bridge } = require('electron').remote.require('./bridge'); | ||||
| const { themeStyle } = require('../theme.js'); | ||||
|  | ||||
| class NoteTextComponent extends React.Component { | ||||
|  | ||||
| @@ -55,6 +56,10 @@ class NoteTextComponent extends React.Component { | ||||
| 		await shared.saveNoteButton_press(this); | ||||
| 	} | ||||
|  | ||||
| 	async saveOneProperty(name, value) { | ||||
| 		await shared.saveOneProperty(this, name, value); | ||||
| 	} | ||||
|  | ||||
| 	scheduleSave() { | ||||
| 		if (this.scheduleSaveTimeout_) clearTimeout(this.scheduleSaveTimeout_); | ||||
| 		this.scheduleSaveTimeout_ = setTimeout(() => { | ||||
| @@ -73,6 +78,7 @@ class NoteTextComponent extends React.Component { | ||||
|  | ||||
| 			this.setState({ | ||||
| 				note: note, | ||||
| 				lastSavedNote: Object.assign({}, note), | ||||
| 				mode: 'view', | ||||
| 			}); | ||||
| 		} | ||||
| @@ -164,7 +170,7 @@ class NoteTextComponent extends React.Component { | ||||
| 			webviewReady: true, | ||||
| 		}); | ||||
|  | ||||
| 		this.webview_.openDevTools();  | ||||
| 		//this.webview_.openDevTools();  | ||||
| 	} | ||||
|  | ||||
| 	webview_ref(element) { | ||||
| @@ -218,6 +224,7 @@ class NoteTextComponent extends React.Component { | ||||
| 		const style = this.props.style; | ||||
| 		const note = this.state.note; | ||||
| 		const body = note ? note.body : ''; | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
|  | ||||
| 		const viewerStyle = { | ||||
| 			width: Math.floor(style.width / 2), | ||||
| @@ -227,12 +234,17 @@ class NoteTextComponent extends React.Component { | ||||
| 			verticalAlign: 'top', | ||||
| 		}; | ||||
|  | ||||
| 		const paddingTop = 14; | ||||
|  | ||||
| 		const editorStyle = { | ||||
| 			width: style.width - viewerStyle.width, | ||||
| 			height: style.height, | ||||
| 			height: style.height - paddingTop, | ||||
| 			overflowY: 'scroll', | ||||
| 			float: 'left', | ||||
| 			verticalAlign: 'top', | ||||
| 			paddingTop: paddingTop + 'px', | ||||
| 			lineHeight: theme.textAreaLineHeight + 'px', | ||||
| 			fontSize: theme.fontSize + 'px', | ||||
| 		}; | ||||
|  | ||||
| 		if (this.state.webviewReady) { | ||||
| @@ -242,7 +254,7 @@ class NoteTextComponent extends React.Component { | ||||
| 				}, | ||||
| 				postMessageSyntax: 'ipcRenderer.sendToHost', | ||||
| 			}; | ||||
| 			const html = this.mdToHtml().render(body, {}, mdOptions); | ||||
| 			const html = this.mdToHtml().render(body, theme, mdOptions); | ||||
| 			this.webview_.send('setHtml', html); | ||||
| 		} | ||||
|  | ||||
|   | ||||
							
								
								
									
										107
									
								
								ElectronClient/app/gui/PromptDialog.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								ElectronClient/app/gui/PromptDialog.jsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| const React = require('react'); | ||||
| const { connect } = require('react-redux'); | ||||
| const { _ } = require('lib/locale.js'); | ||||
| const { themeStyle } = require('../theme.js'); | ||||
|  | ||||
| class PromptDialog extends React.Component { | ||||
|  | ||||
| 	componentWillMount() { | ||||
| 		this.setState({ | ||||
| 			visible: false, | ||||
| 			answer: '', | ||||
| 		}); | ||||
| 		this.focusInput_ = true; | ||||
| 	} | ||||
|  | ||||
| 	componentWillReceiveProps(newProps) { | ||||
| 		if ('visible' in newProps) { | ||||
| 			this.setState({ visible: newProps.visible }); | ||||
| 			if (newProps.visible) this.focusInput_ = true; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	componentDidUpdate() { | ||||
| 		if (this.focusInput_ && this.answerInput_) this.answerInput_.focus(); | ||||
| 		this.focusInput_ = false; | ||||
| 	} | ||||
|  | ||||
| 	render() { | ||||
| 		const style = this.props.style; | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
|  | ||||
| 		const modalLayerStyle = { | ||||
| 			zIndex: 9999, | ||||
| 			position: 'absolute', | ||||
| 			top: 0, | ||||
| 			left: 0, | ||||
| 			width: style.width, | ||||
| 			height: style.height, | ||||
| 			backgroundColor: 'rgba(0,0,0,0.6)', | ||||
| 			display: this.state.visible ? 'flex' : 'none', | ||||
|     		alignItems: 'center', | ||||
|     		justifyContent: 'center', | ||||
| 		}; | ||||
|  | ||||
| 		const promptDialogStyle = { | ||||
| 			backgroundColor: 'white', | ||||
| 			padding: 10, | ||||
| 			display: 'inline-block', | ||||
| 			boxShadow: '6px 6px 20px rgba(0,0,0,0.5)', | ||||
| 		}; | ||||
|  | ||||
| 		const buttonStyle = { | ||||
| 			minWidth: theme.buttonMinWidth, | ||||
| 			minHeight: theme.buttonMinHeight, | ||||
| 			marginLeft: 5, | ||||
| 		}; | ||||
|  | ||||
| 		const inputStyle = { | ||||
| 			width: 0.5 * style.width, | ||||
| 			maxWidth: 400, | ||||
| 		}; | ||||
|  | ||||
| 		const onAccept = () => { | ||||
| 			if (this.props.onAccept) this.props.onAccept(this.state.answer); | ||||
| 			this.setState({ visible: false, answer: '' }); | ||||
| 		} | ||||
|  | ||||
| 		const onReject = () => { | ||||
| 			if (this.props.onReject) this.props.onReject(); | ||||
| 			this.setState({ visible: false, answer: '' }); | ||||
| 		} | ||||
|  | ||||
| 		const onChange = (event) => { | ||||
| 			this.setState({ answer: event.target.value }); | ||||
| 		} | ||||
|  | ||||
| 		const onKeyDown = (event) => { | ||||
| 			if (event.key === 'Enter') { | ||||
| 				onAccept(); | ||||
| 			} else if (event.key === 'Escape') { | ||||
| 				onReject(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return ( | ||||
| 			<div style={modalLayerStyle}> | ||||
| 				<div style={promptDialogStyle}> | ||||
| 					<label style={{ marginRight: 5 }}>{this.props.message ? this.props.message : ''}</label> | ||||
| 					<input | ||||
| 						style={inputStyle} | ||||
| 						ref={input => this.answerInput_ = input} | ||||
| 						value={this.state.answer} | ||||
| 						type="text" | ||||
| 						onChange={(event) => onChange(event)} | ||||
| 						onKeyDown={(event) => onKeyDown(event)} /> | ||||
| 					<div style={{ textAlign: 'right', marginTop: 10 }}> | ||||
| 						<button style={buttonStyle} onClick={() => onAccept()}>OK</button> | ||||
| 						<button style={buttonStyle} onClick={() => onReject()}>Cancel</button> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| module.exports = { PromptDialog }; | ||||
| @@ -2,9 +2,27 @@ const React = require('react'); | ||||
| const { connect } = require('react-redux'); | ||||
| const shared = require('lib/components/shared/side-menu-shared.js'); | ||||
| const { Synchronizer } = require('lib/synchronizer.js'); | ||||
| const { themeStyle } = require('../theme.js'); | ||||
|  | ||||
| class SideBarComponent extends React.Component { | ||||
|  | ||||
| 	style() { | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
|  | ||||
| 		const itemHeight = 20; | ||||
|  | ||||
| 		let style = { | ||||
| 			root: {}, | ||||
| 			listItem: { | ||||
| 				display: 'block', | ||||
| 				cursor: 'pointer', | ||||
| 				height: itemHeight, | ||||
| 			}, | ||||
| 		}; | ||||
|  | ||||
| 		return style; | ||||
| 	} | ||||
|  | ||||
| 	folderItem_click(folder) { | ||||
| 		this.props.dispatch({ | ||||
| 			type: 'FOLDERS_SELECT', | ||||
| @@ -24,15 +42,17 @@ class SideBarComponent extends React.Component { | ||||
| 	} | ||||
|  | ||||
| 	folderItem(folder, selected) { | ||||
| 		let classes = []; | ||||
| 		if (selected) classes.push('selected'); | ||||
| 		return <div key={folder.id} className={classes.join(' ')} onClick={() => {this.folderItem_click(folder)}}>{folder.title}</div> | ||||
| 		const style = Object.assign({}, this.style().listItem, { | ||||
| 			fontWeight: selected ? 'bold' : 'normal', | ||||
| 		}); | ||||
| 		return <a href="#" key={folder.id} style={style} onClick={() => {this.folderItem_click(folder)}}>{folder.title}</a> | ||||
| 	} | ||||
|  | ||||
| 	tagItem(tag, selected) { | ||||
| 		let classes = []; | ||||
| 		if (selected) classes.push('selected'); | ||||
| 		return <div key={tag.id} className={classes.join(' ')} onClick={() => {this.tagItem_click(tag)}}>Tag: {tag.title}</div> | ||||
| 		const style = Object.assign({}, this.style().listItem, { | ||||
| 			fontWeight: selected ? 'bold' : 'normal', | ||||
| 		}); | ||||
| 		return <a href="#" key={tag.id} style={style} onClick={() => {this.tagItem_click(tag)}}>Tag: {tag.title}</a> | ||||
| 	} | ||||
|  | ||||
| 	makeDivider(key) { | ||||
| @@ -44,6 +64,9 @@ class SideBarComponent extends React.Component { | ||||
| 	} | ||||
|  | ||||
| 	render() { | ||||
| 		const theme = themeStyle(this.props.theme); | ||||
| 		const style = Object.assign({}, this.style().root, this.props.style); | ||||
|  | ||||
| 		let items = []; | ||||
|  | ||||
| 		if (this.props.folders.length) { | ||||
| @@ -69,7 +92,7 @@ class SideBarComponent extends React.Component { | ||||
| 		items.push(<div key='sync_report'>{syncReportText}</div>); | ||||
|  | ||||
| 		return ( | ||||
| 			<div className="side-bar" style={this.props.style}> | ||||
| 			<div className="side-bar" style={style}> | ||||
| 				{items} | ||||
| 			</div> | ||||
| 		); | ||||
|   | ||||
| @@ -2,12 +2,11 @@ | ||||
| <html> | ||||
| 	<head> | ||||
| 		<meta charset="UTF-8"> | ||||
| 		<title>Hello World!</title> | ||||
| 		<title>Joplin</title> | ||||
| 		<link rel="stylesheet" href="style.css"> | ||||
| 	</head> | ||||
| 	<body> | ||||
| 		<div id="react-root"></div> | ||||
| 		<!-- <script src="gui/Root.min.js"></script> --> | ||||
| 		<script src="main-html.js"></script> | ||||
| 	</body> | ||||
| </html> | ||||
| </html> | ||||
							
								
								
									
										87
									
								
								ElectronClient/app/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										87
									
								
								ElectronClient/app/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1360,6 +1360,25 @@ | ||||
|         "yargs": "10.0.3" | ||||
|       } | ||||
|     }, | ||||
|     "electron-context-menu": { | ||||
|       "version": "0.9.1", | ||||
|       "resolved": "https://registry.npmjs.org/electron-context-menu/-/electron-context-menu-0.9.1.tgz", | ||||
|       "integrity": "sha1-7U3yDAgEkcPJlqv8s2MVmUajgFg=", | ||||
|       "requires": { | ||||
|         "electron-dl": "1.10.0", | ||||
|         "electron-is-dev": "0.1.2" | ||||
|       } | ||||
|     }, | ||||
|     "electron-dl": { | ||||
|       "version": "1.10.0", | ||||
|       "resolved": "https://registry.npmjs.org/electron-dl/-/electron-dl-1.10.0.tgz", | ||||
|       "integrity": "sha1-+UQWBkBW/G8qhq5JhhTJNSaJCvk=", | ||||
|       "requires": { | ||||
|         "ext-name": "5.0.0", | ||||
|         "pupa": "1.0.0", | ||||
|         "unused-filename": "1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "electron-download-tf": { | ||||
|       "version": "4.3.4", | ||||
|       "resolved": "https://registry.npmjs.org/electron-download-tf/-/electron-download-tf-4.3.4.tgz", | ||||
| @@ -1377,6 +1396,11 @@ | ||||
|         "sumchecker": "2.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "electron-is-dev": { | ||||
|       "version": "0.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-0.1.2.tgz", | ||||
|       "integrity": "sha1-ihBD4ys6HaHD9VPc4oznZCRhZ+M=" | ||||
|     }, | ||||
|     "electron-osx-sign": { | ||||
|       "version": "0.4.7", | ||||
|       "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.7.tgz", | ||||
| @@ -1617,6 +1641,23 @@ | ||||
|       "integrity": "sha512-kkjwkMqj0h4w/sb32ERCDxCQkREMCAgS39DscDnSwDsbxnwwM1BTZySdC3Bn1lhY7vL08n9GoO/fVTynjDgRyQ==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "ext-list": { | ||||
|       "version": "2.2.2", | ||||
|       "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", | ||||
|       "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", | ||||
|       "requires": { | ||||
|         "mime-db": "1.30.0" | ||||
|       } | ||||
|     }, | ||||
|     "ext-name": { | ||||
|       "version": "5.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", | ||||
|       "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", | ||||
|       "requires": { | ||||
|         "ext-list": "2.2.2", | ||||
|         "sort-keys-length": "1.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "extend": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", | ||||
| @@ -2275,6 +2316,11 @@ | ||||
|         "path-is-inside": "1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "is-plain-obj": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", | ||||
|       "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" | ||||
|     }, | ||||
|     "is-posix-bracket": { | ||||
|       "version": "0.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", | ||||
| @@ -2719,8 +2765,7 @@ | ||||
|     "mime-db": { | ||||
|       "version": "1.30.0", | ||||
|       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", | ||||
|       "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", | ||||
|       "dev": true | ||||
|       "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" | ||||
|     }, | ||||
|     "mime-types": { | ||||
|       "version": "2.1.17", | ||||
| @@ -2769,6 +2814,11 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "modify-filename": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/modify-filename/-/modify-filename-1.1.0.tgz", | ||||
|       "integrity": "sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=" | ||||
|     }, | ||||
|     "moment": { | ||||
|       "version": "2.19.1", | ||||
|       "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.1.tgz", | ||||
| @@ -3134,8 +3184,7 @@ | ||||
|     "path-exists": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", | ||||
|       "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", | ||||
|       "dev": true | ||||
|       "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" | ||||
|     }, | ||||
|     "path-is-absolute": { | ||||
|       "version": "1.0.1", | ||||
| @@ -3317,6 +3366,11 @@ | ||||
|       "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "pupa": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/pupa/-/pupa-1.0.0.tgz", | ||||
|       "integrity": "sha1-mpVopa9+ZXuEYqbp1TKHQ1YM7/Y=" | ||||
|     }, | ||||
|     "q": { | ||||
|       "version": "0.9.7", | ||||
|       "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", | ||||
| @@ -3771,6 +3825,22 @@ | ||||
|         "hoek": "4.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "sort-keys": { | ||||
|       "version": "1.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", | ||||
|       "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", | ||||
|       "requires": { | ||||
|         "is-plain-obj": "1.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "sort-keys-length": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", | ||||
|       "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", | ||||
|       "requires": { | ||||
|         "sort-keys": "1.1.2" | ||||
|       } | ||||
|     }, | ||||
|     "source-map": { | ||||
|       "version": "0.6.1", | ||||
|       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", | ||||
| @@ -4890,6 +4960,15 @@ | ||||
|       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", | ||||
|       "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" | ||||
|     }, | ||||
|     "unused-filename": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/unused-filename/-/unused-filename-1.0.0.tgz", | ||||
|       "integrity": "sha1-00CID3GuIRXrqhMlvvBcxmhEacY=", | ||||
|       "requires": { | ||||
|         "modify-filename": "1.1.0", | ||||
|         "path-exists": "3.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "unzip-response": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", | ||||
|   | ||||
| @@ -26,6 +26,7 @@ | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "app-module-path": "^2.2.0", | ||||
|     "electron-context-menu": "^0.9.1", | ||||
|     "fs-extra": "^4.0.2", | ||||
|     "html-entities": "^1.2.1", | ||||
|     "lodash": "^4.17.4", | ||||
|   | ||||
| @@ -6,6 +6,7 @@ const globalStyle = { | ||||
| 	itemMarginTop: 10, | ||||
| 	itemMarginBottom: 10, | ||||
| 	backgroundColor: "#ffffff", | ||||
| 	oddBackgroundColor: "#dddddd", | ||||
| 	color: "#555555", // For regular text | ||||
| 	colorError: "red", | ||||
| 	colorWarn: "#9A5B00", | ||||
| @@ -15,17 +16,21 @@ const globalStyle = { | ||||
| 	selectedColor: '#e5e5e5', | ||||
| 	disabledOpacity: 0.3, | ||||
| 	headerHeight: 20, | ||||
| 	buttonMinWidth: 50, | ||||
| 	buttonMinHeight: 30, | ||||
| 	textAreaLineHeight: 17, | ||||
|  | ||||
| 	raisedBackgroundColor: "#0080EF", | ||||
| 	raisedColor: "#003363", | ||||
| 	raisedHighlightedColor: "#ffffff", | ||||
|  | ||||
| 	// For WebView - must correspond to the properties above | ||||
| 	htmlFontSize: '20x', | ||||
| 	htmlFontSize: '16px', | ||||
| 	htmlColor: 'black', // Note: CSS in WebView component only supports named colors or rgb() notation | ||||
| 	htmlBackgroundColor: 'white', | ||||
| 	htmlDividerColor: 'Gainsboro', | ||||
| 	htmlLinkColor: 'blue', | ||||
| 	htmlLineHeight: '20px', | ||||
| }; | ||||
|  | ||||
| globalStyle.marginRight = globalStyle.margin; | ||||
|   | ||||
| @@ -203,6 +203,8 @@ class MdToHtml { | ||||
| 		if (!options) options = {}; | ||||
| 		if (!options.postMessageSyntax) options.postMessageSyntax = 'postMessage'; | ||||
|  | ||||
| 		console.info(style); | ||||
|  | ||||
| 		const cacheKey = this.makeContentKey(this.loadedResources_, body, style, options); | ||||
| 		if (this.cachedContentKey_ === cacheKey) return this.cachedContent_; | ||||
|  | ||||
| @@ -255,8 +257,13 @@ class MdToHtml { | ||||
| 			body { | ||||
| 				font-size: ` + style.htmlFontSize + `; | ||||
| 				color: ` + style.htmlColor + `; | ||||
| 				line-height: 1.5em; | ||||
| 				line-height: ` + style.htmlLineHeight + `; | ||||
| 				background-color: ` + style.htmlBackgroundColor + `; | ||||
| 				font-family: sans-serif; | ||||
| 			} | ||||
| 			p, h1, h2, h3, h4, ul { | ||||
| 				margin-top: 14px; | ||||
| 				margin-bottom: 14px; | ||||
| 			} | ||||
| 			h1 { | ||||
| 				font-size: 1.2em; | ||||
|   | ||||
| @@ -20,11 +20,12 @@ const globalStyle = { | ||||
| 	raisedHighlightedColor: "#ffffff", | ||||
|  | ||||
| 	// For WebView - must correspond to the properties above | ||||
| 	htmlFontSize: '20x', | ||||
| 	htmlFontSize: '16px', | ||||
| 	htmlColor: 'black', // Note: CSS in WebView component only supports named colors or rgb() notation | ||||
| 	htmlBackgroundColor: 'white', | ||||
| 	htmlDividerColor: 'Gainsboro', | ||||
| 	htmlLinkColor: 'blue', | ||||
| 	htmlLineHeight: '20px', | ||||
| }; | ||||
|  | ||||
| globalStyle.marginRight = globalStyle.margin; | ||||
|   | ||||
							
								
								
									
										9
									
								
								ReactNativeClient/lib/urlUtils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								ReactNativeClient/lib/urlUtils.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| const urlUtils = {}; | ||||
|  | ||||
| urlUtils.hash = function(url) { | ||||
| 	const s = url.split('#'); | ||||
| 	if (s.length <= 1) return ''; | ||||
| 	return s[s.length - 1]; | ||||
| } | ||||
|  | ||||
| module.exports = urlUtils; | ||||
		Reference in New Issue
	
	Block a user