2018-03-09 22:59:12 +02:00
const React = require ( 'react' ) ; const Component = React . Component ;
2019-06-28 01:48:52 +02:00
const { Platform , TouchableOpacity , Linking , View , Switch , StyleSheet , Text , Button , ScrollView , TextInput , Alert } = require ( 'react-native' ) ;
2018-03-09 22:59:12 +02:00
const { connect } = require ( 'react-redux' ) ;
const { ScreenHeader } = require ( 'lib/components/screen-header.js' ) ;
const { _ , setLocale } = require ( 'lib/locale.js' ) ;
const { BaseScreenComponent } = require ( 'lib/components/base-screen.js' ) ;
const { Dropdown } = require ( 'lib/components/Dropdown.js' ) ;
const { themeStyle } = require ( 'lib/components/global-style.js' ) ;
const Setting = require ( 'lib/models/Setting.js' ) ;
const shared = require ( 'lib/components/shared/config-shared.js' ) ;
const SyncTargetRegistry = require ( 'lib/SyncTargetRegistry' ) ;
2018-12-28 22:40:29 +02:00
const { reg } = require ( 'lib/registry.js' ) ;
2019-06-26 01:13:13 +02:00
const NavService = require ( 'lib/services/NavService.js' ) ;
2019-05-06 22:35:29 +02:00
const VersionInfo = require ( 'react-native-version-info' ) . default ;
2019-06-26 01:13:13 +02:00
const { ReportService } = require ( 'lib/services/report.js' ) ;
const { time } = require ( 'lib/time-utils' ) ;
2019-06-28 01:48:52 +02:00
const SearchEngine = require ( 'lib/services/SearchEngine' ) ;
2019-06-26 01:13:13 +02:00
const RNFS = require ( 'react-native-fs' ) ;
2017-07-23 20:26:50 +02:00
2019-07-13 15:51:54 +02:00
import { PermissionsAndroid } from 'react-native' ;
2019-06-14 23:59:27 +02:00
import Slider from '@react-native-community/slider' ;
2017-08-01 19:59:01 +02:00
class ConfigScreenComponent extends BaseScreenComponent {
2018-11-02 02:43:42 +02:00
2017-08-01 19:59:01 +02:00
static navigationOptions ( options ) {
return { header : null } ;
2017-07-30 23:04:26 +02:00
}
2017-07-23 20:26:50 +02:00
2017-08-01 19:59:01 +02:00
constructor ( ) {
super ( ) ;
this . styles _ = { } ;
2018-01-25 21:01:14 +02:00
2019-06-26 01:13:13 +02:00
this . state = {
creatingReport : false ,
} ;
2018-02-06 20:59:36 +02:00
shared . init ( this ) ;
this . checkSyncConfig _ = async ( ) => {
await shared . checkSyncConfig ( this , this . state . settings ) ;
2018-03-09 22:59:12 +02:00
}
2018-02-06 20:59:36 +02:00
2019-06-26 01:13:13 +02:00
this . e2eeConfig _ = ( ) => {
NavService . go ( 'EncryptionConfig' ) ;
}
2019-07-13 15:51:54 +02:00
this . saveButton _press = async ( ) => {
if (
this . state . changedSettingKeys . includes ( 'sync.target' )
&& this . state . settings [ 'sync.target' ] === SyncTargetRegistry . nameToId ( 'filesystem' )
&& ! await this . checkFilesystemPermission ( )
) {
Alert . alert (
_ ( 'Warning' ) ,
2019-07-22 00:27:13 +02:00
_ ( 'In order to use file system synchronisation your permission to write to external storage is required.' )
2019-07-21 09:49:49 +02:00
) ;
2019-07-13 15:51:54 +02:00
// Save settings anyway, even if permission has not been granted
}
2018-02-13 20:26:33 +02:00
return shared . saveSettings ( this ) ;
2018-01-25 21:01:14 +02:00
} ;
2019-06-26 01:13:13 +02:00
this . syncStatusButtonPress _ = ( ) => {
NavService . go ( 'Status' ) ;
}
this . exportDebugButtonPress _ = async ( ) => {
this . setState ( { creatingReport : true } ) ;
const service = new ReportService ( ) ;
const logItems = await reg . logger ( ) . lastEntries ( null ) ;
const logItemRows = [
[ 'Date' , 'Level' , 'Message' ]
] ;
for ( let i = 0 ; i < logItems . length ; i ++ ) {
const item = logItems [ i ] ;
logItemRows . push ( [
time . formatMsToLocal ( item . timestamp , 'MM-DDTHH:mm:ss' ) ,
item . level ,
item . message
] ) ;
}
const logItemCsv = service . csvCreate ( logItemRows ) ;
const itemListCsv = await service . basicItemList ( { format : 'csv' } ) ;
const filePath = RNFS . ExternalDirectoryPath + '/syncReport-' + ( new Date ( ) ) . getTime ( ) + '.txt' ;
const finalText = [ logItemCsv , itemListCsv ] . join ( "\n================================================================================\n" ) ;
await RNFS . writeFile ( filePath , finalText ) ;
alert ( 'Debug report exported to ' + filePath ) ;
this . setState ( { creatingReport : false } ) ;
}
2019-06-28 01:48:52 +02:00
this . fixSearchEngineIndexButtonPress _ = async ( ) => {
this . setState ( { fixingSearchIndex : true } ) ;
await SearchEngine . instance ( ) . rebuildIndex ( ) ;
this . setState ( { fixingSearchIndex : false } ) ;
}
2019-06-26 01:13:13 +02:00
this . logButtonPress _ = ( ) => {
NavService . go ( 'Log' ) ;
}
2018-01-25 21:01:14 +02:00
}
2019-07-13 15:51:54 +02:00
async checkFilesystemPermission ( ) {
if ( Platform . OS !== 'android' ) {
// Not implemented yet
return true ;
}
const hasPermission = await PermissionsAndroid . check (
PermissionsAndroid . PERMISSIONS . WRITE _EXTERNAL _STORAGE ) ;
if ( hasPermission ) {
return true ;
}
const requestResult = await PermissionsAndroid . request (
PermissionsAndroid . PERMISSIONS . WRITE _EXTERNAL _STORAGE ,
{
2019-07-21 09:49:49 +02:00
title : _ ( 'Information' ) ,
2019-07-22 00:27:13 +02:00
message : _ ( 'In order to use file system synchronisation your permission to write to external storage is required.' ) ,
2019-07-13 15:51:54 +02:00
buttonPositive : _ ( 'OK' ) ,
} ,
) ;
return ( requestResult === PermissionsAndroid . RESULTS . GRANTED ) ;
}
2018-04-30 18:38:19 +02:00
UNSAFE _componentWillMount ( ) {
2018-01-25 21:01:14 +02:00
this . setState ( { settings : this . props . settings } ) ;
2017-08-01 19:59:01 +02:00
}
2017-07-30 23:04:26 +02:00
2017-08-01 19:59:01 +02:00
styles ( ) {
const themeId = this . props . theme ;
const theme = themeStyle ( themeId ) ;
if ( this . styles _ [ themeId ] ) return this . styles _ [ themeId ] ;
this . styles _ = { } ;
let styles = {
2017-11-19 01:59:07 +02:00
body : {
flex : 1 ,
2018-03-09 22:59:12 +02:00
justifyContent : 'flex-start' ,
flexDirection : 'column' ,
2017-11-19 01:59:07 +02:00
} ,
2017-08-01 19:59:01 +02:00
settingContainer : {
2017-11-19 01:59:07 +02:00
flex : 1 ,
2018-03-09 22:59:12 +02:00
flexDirection : 'row' ,
alignItems : 'center' ,
2017-08-01 19:59:01 +02:00
borderBottomWidth : 1 ,
borderBottomColor : theme . dividerColor ,
paddingTop : theme . marginTop ,
paddingBottom : theme . marginBottom ,
paddingLeft : theme . marginLeft ,
paddingRight : theme . marginRight ,
} ,
settingText : {
color : theme . color ,
fontSize : theme . fontSize ,
2017-11-19 01:59:07 +02:00
flex : 1 ,
2019-05-26 20:39:07 +02:00
paddingRight : 5 ,
2017-08-01 19:59:01 +02:00
} ,
2018-02-14 21:08:07 +02:00
descriptionText : {
color : theme . color ,
fontSize : theme . fontSize ,
flex : 1 ,
} ,
2019-06-08 01:23:17 +02:00
sliderUnits : {
color : theme . color ,
fontSize : theme . fontSize ,
2019-06-27 01:05:17 +02:00
marginRight : 10 ,
2019-06-08 01:23:17 +02:00
} ,
2019-05-26 20:39:07 +02:00
settingDescriptionText : {
color : theme . color ,
fontSize : theme . fontSize ,
flex : 1 ,
paddingLeft : theme . marginLeft ,
paddingRight : theme . marginRight ,
paddingBottom : theme . marginBottom ,
} ,
2018-05-21 18:24:09 +02:00
permissionText : {
color : theme . color ,
fontSize : theme . fontSize ,
flex : 1 ,
marginTop : 10 ,
} ,
2017-08-01 19:59:01 +02:00
settingControl : {
color : theme . color ,
2017-11-19 01:59:07 +02:00
flex : 1 ,
2017-08-01 19:59:01 +02:00
} ,
2018-03-09 22:59:12 +02:00
}
2017-07-26 19:49:01 +02:00
2019-05-26 20:39:07 +02:00
styles . settingContainerNoBottomBorder = Object . assign ( { } , styles . settingContainer , {
borderBottomWidth : 0 ,
paddingBottom : theme . marginBottom / 2 ,
} ) ;
styles . settingControl . borderBottomWidth = 1 ;
styles . settingControl . borderBottomColor = theme . strongDividerColor ;
2018-02-05 20:32:59 +02:00
2017-08-01 19:59:01 +02:00
styles . switchSettingText = Object . assign ( { } , styles . settingText ) ;
2018-03-09 22:59:12 +02:00
styles . switchSettingText . width = '80%' ;
2017-07-26 19:49:01 +02:00
2017-08-01 19:59:01 +02:00
styles . switchSettingContainer = Object . assign ( { } , styles . settingContainer ) ;
2018-03-09 22:59:12 +02:00
styles . switchSettingContainer . flexDirection = 'row' ;
styles . switchSettingContainer . justifyContent = 'space-between' ;
2017-07-23 20:26:50 +02:00
2017-11-20 20:25:23 +02:00
styles . linkText = Object . assign ( { } , styles . settingText ) ;
styles . linkText . borderBottomWidth = 1 ;
styles . linkText . borderBottomColor = theme . color ;
styles . linkText . flex = 0 ;
2018-03-09 22:59:12 +02:00
styles . linkText . fontWeight = 'normal' ;
2017-11-20 20:25:23 +02:00
2019-06-08 01:23:17 +02:00
styles . headerWrapperStyle = Object . assign ( { } , styles . settingContainer , theme . headerWrapperStyle )
2017-08-01 19:59:01 +02:00
styles . switchSettingControl = Object . assign ( { } , styles . settingControl ) ;
delete styles . switchSettingControl . color ;
2017-11-19 02:23:18 +02:00
//styles.switchSettingControl.width = '20%';
styles . switchSettingControl . flex = 0 ;
2017-08-01 19:59:01 +02:00
this . styles _ [ themeId ] = StyleSheet . create ( styles ) ;
return this . styles _ [ themeId ] ;
2017-07-23 20:26:50 +02:00
}
2019-06-08 01:23:17 +02:00
renderHeader ( key , title ) {
const theme = themeStyle ( this . props . theme ) ;
return (
< View key = { key } style = { this . styles ( ) . headerWrapperStyle } >
< Text style = { theme . headerStyle } > { title } < / T e x t >
< / V i e w >
) ;
}
2019-06-26 01:13:13 +02:00
renderButton ( key , title , clickHandler , options = null ) {
if ( ! options ) options = { } ;
2019-06-28 01:48:52 +02:00
let descriptionComp = null ;
if ( options . description ) {
descriptionComp = (
< View style = { { flex : 1 , marginTop : 10 } } >
< Text style = { this . styles ( ) . descriptionText } > { options . description } < / T e x t >
< / V i e w >
) ;
}
2019-06-26 01:13:13 +02:00
return (
< View key = { key } style = { this . styles ( ) . settingContainer } >
< View style = { { flex : 1 , flexDirection : 'column' } } >
< View style = { { flex : 1 } } >
< Button title = { title } onPress = { clickHandler } disabled = { ! ! options . disabled } / >
< / V i e w >
{ options . statusComp }
2019-06-28 01:48:52 +02:00
{ descriptionComp }
2019-06-26 01:13:13 +02:00
< / V i e w >
< / V i e w >
) ;
}
2019-06-08 01:23:17 +02:00
sectionToComponent ( key , section , settings ) {
const theme = themeStyle ( this . props . theme ) ;
const settingComps = [ ] ;
for ( let i = 0 ; i < section . metadatas . length ; i ++ ) {
const md = section . metadatas [ i ] ;
if ( section . name === 'sync' && md . key === 'sync.resourceDownloadMode' ) {
const syncTargetMd = SyncTargetRegistry . idToMetadata ( settings [ 'sync.target' ] ) ;
if ( syncTargetMd . supportsConfigCheck ) {
const messages = shared . checkSyncConfigMessages ( this ) ;
const statusComp = ! messages . length ? null : (
< View style = { { flex : 1 , marginTop : 10 } } >
< Text style = { this . styles ( ) . descriptionText } > { messages [ 0 ] } < / T e x t >
{ messages . length >= 1 ? ( < View style = { { marginTop : 10 } } > < Text style = { this . styles ( ) . descriptionText } > { messages [ 1 ] } < / T e x t > < / V i e w > ) : n u l l }
< / V i e w > ) ;
2019-06-26 01:13:13 +02:00
settingComps . push ( this . renderButton ( 'check_sync_config_button' , _ ( 'Check synchronisation configuration' ) , this . checkSyncConfig _ , { statusComp : statusComp } ) ) ;
2019-06-08 01:23:17 +02:00
}
}
const settingComp = this . settingToComponent ( md . key , settings [ md . key ] ) ;
settingComps . push ( settingComp ) ;
}
2019-06-26 01:13:13 +02:00
if ( section . name === 'sync' ) {
2019-06-26 19:51:12 +02:00
settingComps . push ( this . renderButton ( 'e2ee_config_button' , _ ( 'Encryption Config' ) , this . e2eeConfig _ ) ) ;
2019-06-26 01:13:13 +02:00
}
2019-06-08 01:23:17 +02:00
const headerWrapperStyle = this . styles ( ) . headerWrapperStyle ;
return (
< View key = { key } >
{ this . renderHeader ( section . name , Setting . sectionNameToLabel ( section . name ) ) }
< View >
{ settingComps }
< / V i e w >
< / V i e w >
) ;
}
2017-07-31 22:51:24 +02:00
settingToComponent ( key , value ) {
2017-11-19 01:59:07 +02:00
const themeId = this . props . theme ;
const theme = themeStyle ( themeId ) ;
2017-07-23 20:26:50 +02:00
let output = null ;
const updateSettingValue = ( key , value ) => {
2018-02-13 20:26:33 +02:00
return shared . updateSettingValue ( this , key , value ) ;
2018-03-09 22:59:12 +02:00
}
2017-07-23 20:26:50 +02:00
2017-07-31 22:51:24 +02:00
const md = Setting . settingMetadata ( key ) ;
2019-05-26 20:39:07 +02:00
const settingDescription = md . description ? md . description ( ) : '' ;
2017-07-31 22:51:24 +02:00
if ( md . isEnum ) {
value = value . toString ( ) ;
2017-07-23 20:26:50 +02:00
let items = [ ] ;
2017-07-31 22:51:24 +02:00
const settingOptions = md . options ( ) ;
2017-07-23 20:26:50 +02:00
for ( let k in settingOptions ) {
if ( ! settingOptions . hasOwnProperty ( k ) ) continue ;
2017-11-19 01:59:07 +02:00
items . push ( { label : settingOptions [ k ] , value : k . toString ( ) } ) ;
2017-07-23 20:26:50 +02:00
}
2019-05-26 20:39:07 +02:00
const descriptionComp = ! settingDescription ? null : < Text style = { this . styles ( ) . settingDescriptionText } > { settingDescription } < / T e x t >
const containerStyle = ! settingDescription ? this . styles ( ) . settingContainer : this . styles ( ) . settingContainerNoBottomBorder ;
2017-07-23 20:26:50 +02:00
return (
2019-06-08 01:23:17 +02:00
< View key = { key } style = { { flexDirection : 'column' , borderBottomWidth : 1 , borderBottomColor : theme . dividerColor } } >
< View style = { containerStyle } >
2019-05-26 20:39:07 +02:00
< Text key = "label" style = { this . styles ( ) . settingText } > { md . label ( ) } < / T e x t >
< Dropdown
key = "control"
style = { this . styles ( ) . settingControl }
items = { items }
selectedValue = { value }
itemListStyle = { {
backgroundColor : theme . backgroundColor ,
} }
headerStyle = { {
color : theme . color ,
fontSize : theme . fontSize ,
} }
itemStyle = { {
color : theme . color ,
fontSize : theme . fontSize ,
} }
onValueChange = { ( itemValue , itemIndex ) => { updateSettingValue ( key , itemValue ) ; } }
/ >
< / V i e w >
{ descriptionComp }
2017-07-23 20:26:50 +02:00
< / V i e w >
) ;
2017-07-31 22:51:24 +02:00
} else if ( md . type == Setting . TYPE _BOOL ) {
2017-07-26 19:49:01 +02:00
return (
2017-08-01 19:59:01 +02:00
< View key = { key } style = { this . styles ( ) . switchSettingContainer } >
2018-03-09 22:59:12 +02:00
< Text key = "label" style = { this . styles ( ) . switchSettingText } > { md . label ( ) } < / T e x t >
< Switch key = "control" style = { this . styles ( ) . switchSettingControl } value = { value } onValueChange = { ( value ) => updateSettingValue ( key , value ) } / >
2017-07-26 19:49:01 +02:00
< / V i e w >
) ;
2017-07-31 22:51:24 +02:00
} else if ( md . type == Setting . TYPE _INT ) {
2019-05-06 22:35:29 +02:00
const unitLabel = md . unitLabel ? md . unitLabel ( value ) : value ;
2017-07-25 23:55:26 +02:00
return (
2017-08-01 19:59:01 +02:00
< View key = { key } style = { this . styles ( ) . settingContainer } >
2018-03-09 22:59:12 +02:00
< Text key = "label" style = { this . styles ( ) . settingText } > { md . label ( ) } < / T e x t >
2019-06-27 01:05:17 +02:00
< View style = { { display : 'flex' , flexDirection : 'row' , alignItems : 'center' , flex : 1 } } >
2019-06-08 01:23:17 +02:00
< Text style = { this . styles ( ) . sliderUnits } > { unitLabel } < / T e x t >
2019-06-27 01:05:17 +02:00
< Slider key = "control" minimumTrackTintColor = { theme . color } maximumTrackTintColor = { theme . color } style = { { flex : 1 } } step = { md . step } minimumValue = { md . minimum } maximumValue = { md . maximum } value = { value } onValueChange = { ( value ) => updateSettingValue ( key , value ) } / >
2019-05-06 22:35:29 +02:00
< / V i e w >
2017-07-25 23:55:26 +02:00
< / V i e w >
) ;
2018-01-25 21:01:14 +02:00
} else if ( md . type == Setting . TYPE _STRING ) {
return (
< View key = { key } style = { this . styles ( ) . settingContainer } >
2018-03-09 22:59:12 +02:00
< Text key = "label" style = { this . styles ( ) . settingText } > { md . label ( ) } < / T e x t >
2019-06-08 01:23:17 +02:00
< TextInput autoCorrect = { false } autoCompleteType = "off" selectionColor = { theme . textSelectionColor } autoCapitalize = "none" key = "control" style = { this . styles ( ) . settingControl } value = { value } onChangeText = { ( value ) => updateSettingValue ( key , value ) } secureTextEntry = { ! ! md . secure } / >
2018-01-25 21:01:14 +02:00
< / V i e w >
) ;
2017-07-26 19:49:01 +02:00
} else {
2018-01-25 21:01:14 +02:00
//throw new Error('Unsupported setting type: ' + md.type);
2017-07-23 20:26:50 +02:00
}
return output ;
}
render ( ) {
2018-01-25 21:01:14 +02:00
const settings = this . state . settings ;
2017-07-23 20:26:50 +02:00
2019-06-08 01:23:17 +02:00
const settingComps = shared . settingsToComponents2 ( this , 'mobile' , settings ) ;
2018-02-06 20:59:36 +02:00
2019-06-26 19:51:12 +02:00
settingComps . push ( this . renderHeader ( 'tools' , _ ( 'Tools' ) ) ) ;
2019-06-26 01:13:13 +02:00
2019-06-26 19:51:12 +02:00
settingComps . push ( this . renderButton ( 'status_button' , _ ( 'Sync Status' ) , this . syncStatusButtonPress _ ) ) ;
settingComps . push ( this . renderButton ( 'log_button' , _ ( 'Log' ) , this . logButtonPress _ ) ) ;
2019-06-26 01:13:13 +02:00
settingComps . push ( this . renderButton ( 'export_report_button' , this . state . creatingReport ? _ ( 'Creating report...' ) : _ ( 'Export Debug Report' ) , this . exportDebugButtonPress _ , { disabled : this . state . creatingReport } ) ) ;
2019-07-22 00:27:13 +02:00
settingComps . push ( this . renderButton ( 'fix_search_engine_index' , this . state . fixingSearchIndex ? _ ( 'Fixing search index...' ) : _ ( 'Fix search index' ) , this . fixSearchEngineIndexButtonPress _ , { disabled : this . state . fixingSearchIndex , description : _ ( 'Use this to rebuild the search index if there is a problem with search. It may take a long time depending on the number of notes.' ) } ) ) ;
2019-06-26 01:13:13 +02:00
2019-06-08 01:23:17 +02:00
settingComps . push ( this . renderHeader ( 'moreInfo' , _ ( 'More information' ) ) ) ;
2018-03-09 11:09:13 +02:00
2018-05-21 18:24:09 +02:00
if ( Platform . OS === 'android' && Platform . Version >= 23 ) {
// Note: `PermissionsAndroid` doesn't work so we have to ask the user to manually
// set these permissions. https://stackoverflow.com/questions/49771084/permission-always-returns-never-ask-again
2019-06-08 01:23:17 +02:00
2018-05-21 18:24:09 +02:00
settingComps . push (
< View key = "permission_info" style = { this . styles ( ) . settingContainer } >
< View key = "permission_info_wrapper" >
< Text key = "perm1a" style = { this . styles ( ) . settingText } > { _ ( 'To work correctly, the app needs the following permissions. Please enable them in your phone settings, in Apps > Joplin > Permissions' ) } < / T e x t >
< Text key = "perm2" style = { this . styles ( ) . permissionText } > { _ ( '- Storage: to allow attaching files to notes and to enable filesystem synchronisation.' ) } < / T e x t >
< Text key = "perm3" style = { this . styles ( ) . permissionText } > { _ ( '- Camera: to allow taking a picture and attaching it to a note.' ) } < / T e x t >
< Text key = "perm4" style = { this . styles ( ) . permissionText } > { _ ( '- Location: to allow attaching geo-location information to a note.' ) } < / T e x t >
< / V i e w >
< / V i e w >
) ;
}
2018-03-09 11:09:13 +02:00
settingComps . push (
< View key = "donate_link" style = { this . styles ( ) . settingContainer } >
2019-04-18 15:59:17 +02:00
< TouchableOpacity onPress = { ( ) => { Linking . openURL ( 'https://joplinapp.org/donate/' ) } } >
2018-03-09 22:59:12 +02:00
< Text key = "label" style = { this . styles ( ) . linkText } > { _ ( 'Make a donation' ) } < / T e x t >
2018-03-09 11:09:13 +02:00
< / T o u c h a b l e O p a c i t y >
< / V i e w >
) ;
2018-11-02 02:43:42 +02:00
2017-11-20 20:25:23 +02:00
settingComps . push (
< View key = "website_link" style = { this . styles ( ) . settingContainer } >
2019-04-18 15:59:17 +02:00
< TouchableOpacity onPress = { ( ) => { Linking . openURL ( 'https://joplinapp.org/' ) } } >
2018-03-09 22:59:12 +02:00
< Text key = "label" style = { this . styles ( ) . linkText } > { _ ( 'Joplin website' ) } < / T e x t >
2017-11-20 20:25:23 +02:00
< / T o u c h a b l e O p a c i t y >
< / V i e w >
) ;
settingComps . push (
< View key = "privacy_link" style = { this . styles ( ) . settingContainer } >
2019-04-18 15:59:17 +02:00
< TouchableOpacity onPress = { ( ) => { Linking . openURL ( 'https://joplinapp.org/privacy/' ) } } >
2018-03-09 22:59:12 +02:00
< Text key = "label" style = { this . styles ( ) . linkText } > Privacy Policy < / T e x t >
2017-11-20 20:25:23 +02:00
< / T o u c h a b l e O p a c i t y >
< / V i e w >
) ;
2017-07-23 20:26:50 +02:00
2018-11-02 02:43:42 +02:00
settingComps . push (
2018-12-28 22:40:29 +02:00
< View key = "version_info_app" style = { this . styles ( ) . settingContainer } >
2019-03-08 19:31:48 +02:00
< Text style = { this . styles ( ) . settingText } > { "Joplin " + VersionInfo . appVersion } < / T e x t >
2018-12-28 22:40:29 +02:00
< / V i e w >
) ;
settingComps . push (
< View key = "version_info_db" style = { this . styles ( ) . settingContainer } >
< Text style = { this . styles ( ) . settingText } > { _ ( 'Database v%s' , reg . db ( ) . version ( ) ) } < / T e x t >
< / V i e w >
) ;
settingComps . push (
< View key = "version_info_fts" style = { this . styles ( ) . settingContainer } >
< Text style = { this . styles ( ) . settingText } > { _ ( 'FTS enabled: %d' , this . props . settings [ 'db.ftsEnabled' ] ) } < / T e x t >
2018-11-02 02:43:42 +02:00
< / V i e w >
) ;
2017-07-23 20:26:50 +02:00
return (
2017-08-01 19:59:01 +02:00
< View style = { this . rootStyle ( this . props . theme ) . root } >
2018-03-09 22:59:12 +02:00
< ScreenHeader
title = { _ ( 'Configuration' ) }
showSaveButton = { true }
2019-07-11 19:26:04 +02:00
showSearchButton = { false }
showSideMenuButton = { false }
2018-03-09 22:59:12 +02:00
saveButtonDisabled = { ! this . state . changedSettingKeys . length }
onSaveButtonPress = { this . saveButton _press }
/ >
< ScrollView >
{ settingComps }
< / S c r o l l V i e w >
2017-07-23 20:26:50 +02:00
< / V i e w >
) ;
}
2018-03-09 22:59:12 +02:00
2017-07-23 20:26:50 +02:00
}
2018-03-09 22:59:12 +02:00
const ConfigScreen = connect (
( state ) => {
return {
settings : state . settings ,
theme : state . settings . theme ,
} ;
}
) ( ConfigScreenComponent )
2017-07-23 20:26:50 +02:00
2018-11-02 02:43:42 +02:00
module . exports = { ConfigScreen } ;