define ( [
'jquery' ,
'/common/toolbar.js' ,
'/bower_components/nthen/index.js' ,
'/common/sframe-common.js' ,
'/common/common-interface.js' ,
'/common/common-ui-elements.js' ,
'/common/common-util.js' ,
'/common/common-hash.js' ,
'/customize/messages.js' ,
'/common/hyperscript.js' ,
'/common/common-credential.js' ,
'/customize/application_config.js' ,
'/api/config' ,
'/common/make-backup.js' ,
'/common/common-feedback.js' ,
'/common/jscolor.js' ,
'/bower_components/file-saver/FileSaver.min.js' ,
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css' ,
'css!/bower_components/components-font-awesome/css/font-awesome.min.css' ,
'less!/settings/app-settings.less' ,
] , function (
$ ,
Toolbar ,
nThen ,
SFCommon ,
UI ,
UIElements ,
Util ,
Hash ,
Messages ,
h ,
Cred ,
AppConfig ,
ApiConfig ,
Backup ,
Feedback
) {
var saveAs = window . saveAs ;
var APP = window . APP = { } ;
var common ;
var metadataMgr ;
var privateData ;
var sframeChan ;
var categories = {
'account' : [
'cp-settings-own-drive' ,
'cp-settings-info-block' ,
'cp-settings-displayname' ,
'cp-settings-language-selector' ,
'cp-settings-mediatag-size' ,
'cp-settings-change-password' ,
'cp-settings-delete'
] ,
'security' : [
'cp-settings-logout-everywhere' ,
'cp-settings-autostore' ,
'cp-settings-safe-links' ,
'cp-settings-userfeedback' ,
'cp-settings-cache' ,
] ,
'drive' : [
'cp-settings-resettips' ,
'cp-settings-drive-duplicate' ,
'cp-settings-thumbnails' ,
'cp-settings-drive-backup' ,
'cp-settings-drive-import-local' ,
'cp-settings-trim-history'
//'cp-settings-drive-reset'
] ,
'cursor' : [
'cp-settings-cursor-color' ,
'cp-settings-cursor-share' ,
'cp-settings-cursor-show' ,
] ,
'pad' : [
'cp-settings-pad-width' ,
'cp-settings-pad-spellcheck' ,
'cp-settings-pad-notif' ,
] ,
'code' : [
'cp-settings-code-indent-unit' ,
'cp-settings-code-indent-type' ,
'cp-settings-code-brackets' ,
'cp-settings-code-font-size' ,
'cp-settings-code-spellcheck' ,
] ,
'kanban' : [
'cp-settings-kanban-tags' ,
] ,
'subscription' : {
onClick : function ( ) {
var urls = common . getMetadataMgr ( ) . getPrivateData ( ) . accounts ;
window . open ( urls . upgradeURL ) ;
Feedback . send ( 'SUBSCRIPTION_BUTTON' ) ;
}
}
} ;
if ( AppConfig . disableFeedback ) {
var feedbackIdx = categories . account . indexOf ( 'cp-settings-userfeedback' ) ;
categories . account . splice ( feedbackIdx , 1 ) ;
}
if ( AppConfig . disableProfile ) {
var displaynameIdx = categories . account . indexOf ( 'cp-settings-displayname' ) ;
categories . account . splice ( displaynameIdx , 1 ) ;
}
if ( ! ApiConfig . allowSubscriptions ) {
delete categories . subscription ;
}
var create = { } ;
var SPECIAL _HINTS _HANDLER = {
safeLinks : function ( ) {
return $ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. html ( Messages . _getKey ( 'settings_safeLinksHint' , [ '<span class="fa fa-shhare-alt"></span>' ] ) ) ;
} ,
} ;
var DEFAULT _HINT _HANDLER = function ( safeKey ) {
return $ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages [ 'settings_' + safeKey + 'Hint' ] || 'Coming soon...' ) ;
} ;
var makeBlock = function ( key , getter , full ) {
var safeKey = key . replace ( /-([a-z])/g , function ( g ) { return g [ 1 ] . toUpperCase ( ) ; } ) ;
create [ key ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-' + key + ' cp-sidebarlayout-element' } ) ;
if ( full ) {
$ ( '<label>' ) . text ( Messages [ 'settings_' + safeKey + 'Title' ] || key ) . appendTo ( $div ) ;
// if this block's hint needs a special renderer, then create it in SPECIAL_HINTS_HANLDER
// otherwise the default will be used
var hintFunction = ( typeof ( SPECIAL _HINTS _HANDLER [ safeKey ] ) === 'function' ) ?
SPECIAL _HINTS _HANDLER [ safeKey ] :
DEFAULT _HINT _HANDLER ;
hintFunction ( safeKey ) . appendTo ( $div ) ;
}
getter ( function ( content ) {
if ( content === false ) {
$div . remove ( ) ;
$div = undefined ;
return ;
}
$div . append ( content ) ;
} , $div ) ;
return $div ;
} ;
} ;
// Account settings
create [ 'info-block' ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-info-block' } ) ;
var $account = $ ( '<div>' , { 'class' : 'cp-sidebarlayout-element' } ) . appendTo ( $div ) ;
var accountName = privateData . accountName ;
var $label = $ ( '<span>' , { 'class' : 'label' } ) . text ( Messages . user _accountName ) ;
var $name = $ ( '<span>' ) . text ( accountName || '' ) ;
if ( ! accountName ) {
$label . text ( '' ) ;
$name . text ( Messages . settings _anonymous ) ;
}
$account . append ( $label ) . append ( $name ) ;
var publicKey = privateData . edPublic ;
if ( publicKey ) {
var $key = $ ( '<div>' , { 'class' : 'cp-sidebarlayout-element' } ) . appendTo ( $div ) ;
var userHref = Hash . getPublicSigningKeyString ( privateData . origin , accountName , publicKey ) ;
var $pubLabel = $ ( '<span>' , { 'class' : 'label' } )
. text ( Messages . settings _publicSigningKey ) ;
$key . append ( $pubLabel ) . append ( UI . dialog . selectable ( userHref ) ) ;
}
return $div ;
} ;
// Create the block containing the display name field
create [ 'displayname' ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-displayname cp-sidebarlayout-element' } ) ;
$ ( '<label>' , { 'for' : 'cp-settings-displayname' } ) . text ( Messages . user _displayName ) . appendTo ( $div ) ;
var $inputBlock = $ ( '<div>' , { 'class' : 'cp-sidebarlayout-input-block' } ) . appendTo ( $div ) ;
var $input = $ ( '<input>' , {
'type' : 'text' ,
'id' : 'cp-settings-displayname' ,
'placeholder' : Messages . anonymous
} ) . appendTo ( $inputBlock ) ;
var $save = $ ( '<button>' , { 'class' : 'btn btn-primary' } ) . text ( Messages . settings _save ) . appendTo ( $inputBlock ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) . hide ( ) . appendTo ( $div ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) . hide ( ) . appendTo ( $div ) ;
var displayName = metadataMgr . getUserData ( ) . name || '' ;
$input . val ( displayName ) ;
// When the display name is changed (enter or button clicked)
var todo = function ( ) {
displayName = $input . val ( ) ;
if ( displayName === metadataMgr . getUserData ( ) . name ) { return ; }
$spinner . show ( ) ;
common . setDisplayName ( displayName , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ;
$input . on ( 'keyup' , function ( e ) {
if ( $input . val ( ) !== displayName ) { $ok . hide ( ) ; }
if ( e . which === 13 ) { todo ( ) ; }
} ) ;
$save . click ( todo ) ;
// On remote change
var onChange = function ( ) {
if ( metadataMgr . getUserData ( ) . name !== $input . val ( ) ) {
$input . val ( metadataMgr . getUserData ( ) . name ) ;
$input . focusout ( ) ;
}
} ;
metadataMgr . onChange ( onChange ) ;
return $div ;
} ;
create [ 'language-selector' ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-language-selector cp-sidebarlayout-element' } ) ;
$ ( '<label>' ) . text ( Messages . language ) . appendTo ( $div ) ;
var $b = common . createLanguageSelector ( $div ) ;
$b . find ( 'button' ) . addClass ( 'btn btn-secondary' ) ;
return $div ;
} ;
create [ 'logout-everywhere' ] = function ( ) {
if ( ! common . isLoggedIn ( ) ) { return ; }
var $div = $ ( '<div>' , { 'class' : 'cp-settings-logout-everywhere cp-sidebarlayout-element' } ) ;
$ ( '<label>' ) . text ( Messages . settings _logoutEverywhereTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _logoutEverywhere ) . appendTo ( $div ) ;
var $button = $ ( '<button>' , {
id : 'cp-settings-logout-everywhere' ,
'class' : 'btn btn-primary'
} ) . text ( Messages . settings _logoutEverywhereButton )
. appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) . hide ( ) . appendTo ( $div ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) . hide ( ) . appendTo ( $div ) ;
$button . click ( function ( ) {
UI . confirm ( Messages . settings _logoutEverywhereConfirm , function ( yes ) {
if ( ! yes ) { return ; }
$spinner . show ( ) ;
$ok . hide ( ) ;
Feedback . send ( 'LOGOUT_EVERYWHERE' ) ;
sframeChan . query ( 'Q_SETTINGS_LOGOUT' , null , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
window . setTimeout ( function ( ) {
$ok . fadeOut ( 1500 ) ;
} , 2500 ) ;
} ) ;
} ) ;
} ) ;
return $div ;
} ;
create [ 'autostore' ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-autostore cp-sidebarlayout-element' } ) ;
$ ( '<span>' , { 'class' : 'label' } ) . text ( Messages . settings _autostoreTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. append ( Messages . settings _autostoreHint ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var opt1 = UI . createRadio ( 'cp-settings-autostore' , 'cp-settings-autostore-no' ,
Messages . settings _autostoreNo , false , {
input : { value : - 1 } ,
label : { class : 'noTitle' }
} ) ;
var opt2 = UI . createRadio ( 'cp-settings-autostore' , 'cp-settings-autostore-maybe' ,
Messages . settings _autostoreMaybe , true , {
input : { value : 0 } ,
label : { class : 'noTitle' }
} ) ;
var opt3 = UI . createRadio ( 'cp-settings-autostore' , 'cp-settings-autostore-yes' ,
Messages . settings _autostoreYes , false , {
input : { value : 1 } ,
label : { class : 'noTitle' }
} ) ;
var $div2 = $ ( h ( 'div.cp-settings-radio-container' , [
opt3 ,
opt2 ,
opt1
] ) ) . appendTo ( $div ) ;
$div . find ( 'input[type="radio"]' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $ ( 'input:radio[name="cp-settings-autostore"]:checked' ) . val ( ) ;
val = Number ( val ) || 0 ;
common . setAttribute ( [ 'general' , 'autostore' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$ok . hide ( ) . appendTo ( $div2 ) ;
$spinner . hide ( ) . appendTo ( $div2 ) ;
common . getAttribute ( [ 'general' , 'autostore' ] , function ( err , val ) {
if ( val === 1 ) { return void $ ( '#cp-settings-autostore-yes' ) . prop ( 'checked' , true ) ; }
if ( val === - 1 ) { return void $ ( '#cp-settings-autostore-no' ) . prop ( 'checked' , true ) ; }
$ ( '#cp-settings-autostore-maybe' ) . prop ( 'checked' , true ) ;
} ) ;
return $div ;
} ;
create [ 'userfeedback' ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-userfeedback cp-sidebarlayout-element' } ) ;
$ ( '<span>' , { 'class' : 'label' } ) . text ( Messages . settings _userFeedbackTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. append ( Messages . settings _userFeedbackHint1 )
. append ( Messages . settings _userFeedbackHint2 ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-userfeedback' ,
Messages . settings _userFeedback ,
false , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) || false ;
common . setAttribute ( [ 'general' , 'allowUserFeedback' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
if ( privateData . feedbackAllowed ) {
$checkbox [ 0 ] . checked = true ;
}
return $div ;
} ;
// XXX
Messages . settings _cacheTitle = "Cache" ;
Messages . settings _cacheHint = "CryptPad stores parts of your documents in your browser's memory in order to save network usage and improve loading times. The documents stored in cache can then be loaded faster the next time you visit them. You can disable the cache if your device doesn't have a lot of free storage space. For security reasons, the cache is always cleared when you log out, but you can clear it manually if you want to reclaim storage space on your machine." ;
Messages . settings _cacheCheckbox = "Enable cache on this device" ;
Messages . settings _cacheButton = "Clear existing cache" ;
makeBlock ( 'cache' , function ( cb ) {
var store = window . cryptpadStore ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-cache' ,
Messages . settings _cacheCheckbox ,
false , { label : { class : 'noTitle' } } ) ) ;
var spinner = UI . makeSpinner ( $cbox ) ;
// Checkbox: "Enable safe links"
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
spinner . spin ( ) ;
var val = ! $checkbox . is ( ':checked' ) ? '1' : undefined ;
store . put ( 'disableCache' , val , function ( ) {
sframeChan . query ( 'Q_CACHE_DISABLE' , {
disabled : Boolean ( val )
} , function ( ) {
spinner . done ( ) ;
} ) ;
} ) ;
} ) ;
store . get ( 'disableCache' , function ( val ) {
if ( ! val ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
var button = h ( 'button.btn.btn-danger' , [
h ( 'i.fa.fa-trash-o' ) ,
h ( 'span' , Messages . settings _cacheButton )
] ) ;
var buttonContainer = h ( 'div.cp-settings-clear-cache' , button ) ;
var spinner2 = UI . makeSpinner ( $ ( buttonContainer ) ) ;
UI . confirmButton ( button , {
classes : 'btn-danger'
} , function ( ) {
spinner2 . spin ( ) ;
sframeChan . query ( 'Q_CLEAR_CACHE' , null , function ( ) {
spinner2 . done ( ) ;
} ) ;
} ) ;
cb ( [
$cbox [ 0 ] ,
buttonContainer
] ) ;
} , true ) ;
create [ 'delete' ] = function ( ) {
if ( ! common . isLoggedIn ( ) ) { return ; }
var $div = $ ( '<div>' , { 'class' : 'cp-settings-delete cp-sidebarlayout-element' } ) ;
$ ( '<span>' , { 'class' : 'label' } ) . text ( Messages . settings _deleteTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. append ( Messages . settings _deleteHint ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var $button = $ ( '<button>' , { 'id' : 'cp-settings-delete' , 'class' : 'btn btn-danger' } )
. text ( Messages . settings _deleteButton ) . appendTo ( $div ) ;
$button . click ( function ( ) {
$spinner . show ( ) ;
UI . confirm ( Messages . settings _deleteConfirm , function ( yes ) {
if ( ! yes ) { return ; }
sframeChan . query ( "Q_SETTINGS_DELETE_ACCOUNT" , null , function ( err , data ) {
// Owned drive
if ( data . state === true ) {
sframeChan . query ( 'Q_SETTINGS_LOGOUT' , null , function ( ) { } ) ;
UI . alert ( Messages . settings _deleted , function ( ) {
common . gotoURL ( '/' ) ;
} ) ;
$ok . show ( ) ;
$spinner . hide ( ) ;
return ;
}
// Not owned drive
var msg = h ( 'div.cp-app-settings-delete-alert' , [
h ( 'p' , Messages . settings _deleteModal ) ,
h ( 'pre' , JSON . stringify ( data , 0 , 2 ) )
] ) ;
UI . alert ( msg ) ;
$spinner . hide ( ) ;
} ) ;
} ) ;
// TODO
/ *
UI . confirm ( "Are you sure?" , function ( yes ) {
// Logout everywhere
// Disconnect other tabs
// Remove owned pads
// Remove owned drive
// Remove pinstore
// Alert: "Account deleted", press OK to be redirected to the home page
$spinner . hide ( ) ;
} ) ; * /
} ) ;
$spinner . hide ( ) . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $div ) ;
return $div ;
} ;
create [ 'change-password' ] = function ( ) {
if ( ! common . isLoggedIn ( ) ) { return ; }
var $div = $ ( '<div>' , { 'class' : 'cp-settings-change-password cp-sidebarlayout-element' } ) ;
$ ( '<span>' , { 'class' : 'label' } ) . text ( Messages . settings _changePasswordTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. append ( Messages . settings _changePasswordHint ) . appendTo ( $div ) ;
// var publicKey = privateData.edPublic;
var form = h ( 'div' , [
UI . passwordInput ( {
id : 'cp-settings-change-password-current' ,
placeholder : Messages . settings _changePasswordCurrent
} , true ) ,
h ( 'br' ) ,
UI . passwordInput ( {
id : 'cp-settings-change-password-new' ,
placeholder : Messages . settings _changePasswordNew
} , true ) ,
UI . passwordInput ( {
id : 'cp-settings-change-password-new2' ,
placeholder : Messages . settings _changePasswordNewConfirm
} , true ) ,
h ( 'button.btn.btn-primary' , Messages . settings _changePasswordButton )
] ) ;
$ ( form ) . appendTo ( $div ) ;
var updateBlock = function ( data , cb ) {
sframeChan . query ( 'Q_CHANGE_USER_PASSWORD' , data , function ( err , obj ) {
if ( err || obj . error ) { return void cb ( { error : err || obj . error } ) ; }
cb ( obj ) ;
} ) ;
} ;
var todo = function ( ) {
var oldPassword = $ ( form ) . find ( '#cp-settings-change-password-current' ) . val ( ) ;
var newPassword = $ ( form ) . find ( '#cp-settings-change-password-new' ) . val ( ) ;
var newPasswordConfirm = $ ( form ) . find ( '#cp-settings-change-password-new2' ) . val ( ) ;
/* basic validation */
if ( ! Cred . isLongEnoughPassword ( newPassword ) ) {
var warning = Messages . _getKey ( 'register_passwordTooShort' , [
Cred . MINIMUM _PASSWORD _LENGTH
] ) ;
return void UI . alert ( warning ) ;
}
if ( newPassword !== newPasswordConfirm ) {
UI . alert ( Messages . register _passwordsDontMatch ) ;
return ;
}
if ( oldPassword === newPassword ) {
return void UI . alert ( Messages . settings _changePasswordNewPasswordSameAsOld ) ;
}
UI . confirm ( Messages . settings _changePasswordConfirm ,
function ( yes ) {
if ( ! yes ) { return ; }
UI . addLoadingScreen ( {
hideTips : true ,
loadingText : Messages . settings _changePasswordPending ,
} ) ;
updateBlock ( {
password : oldPassword ,
newPassword : newPassword
} , function ( obj ) {
UI . removeLoadingScreen ( ) ;
if ( obj && obj . error ) {
// TODO more specific error message?
UI . alert ( Messages . settings _changePasswordError ) ;
}
} ) ;
} , {
ok : Messages . register _writtenPassword ,
cancel : Messages . register _cancel ,
cancelClass : 'btn.btn-safe' ,
okClass : 'btn.btn-danger' ,
reverseOrder : true ,
done : function ( $dialog ) {
$dialog . find ( '> div' ) . addClass ( 'half' ) ;
} ,
} , true ) ;
} ;
$ ( form ) . find ( 'button' ) . click ( function ( ) {
todo ( ) ;
} ) ;
$ ( form ) . find ( 'input' ) . keydown ( function ( e ) {
// Save on Enter
if ( e . which === 13 ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
todo ( ) ;
}
} ) ;
return $div ;
} ;
makeBlock ( 'own-drive' , function ( cb , $div ) {
if ( privateData . isDriveOwned || ! common . isLoggedIn ( ) ) {
return void cb ( false ) ;
}
$div . addClass ( 'alert alert-warning' ) ;
var form = h ( 'div' , [
UI . passwordInput ( {
id : 'cp-settings-migrate-password' ,
placeholder : Messages . settings _changePasswordCurrent
} , true ) ,
h ( 'button.btn.btn-primary' , Messages . settings _ownDriveButton )
] ) ;
var $form = $ ( form ) ;
var spinner = UI . makeSpinner ( $form ) ;
var todo = function ( ) {
var password = $form . find ( '#cp-settings-migrate-password' ) . val ( ) ;
if ( ! password ) { return ; }
spinner . spin ( ) ;
UI . confirm ( Messages . settings _ownDriveConfirm , function ( yes ) {
if ( ! yes ) { return ; }
var data = {
password : password ,
newPassword : password
} ;
UI . addLoadingScreen ( {
hideTips : true ,
loadingText : Messages . settings _ownDrivePending ,
} ) ;
sframeChan . query ( 'Q_CHANGE_USER_PASSWORD' , data , function ( err , obj ) {
UI . removeLoadingScreen ( ) ;
if ( err || obj . error ) { return UI . alert ( Messages . settings _changePasswordError ) ; }
spinner . done ( ) ;
} ) ;
} ) ;
} ;
$form . find ( 'button' ) . click ( function ( ) {
todo ( ) ;
} ) ;
$form . find ( 'input' ) . keydown ( function ( e ) {
// Save on Enter
if ( e . which === 13 ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
todo ( ) ;
}
} ) ;
cb ( form ) ;
} , true ) ;
makeBlock ( 'mediatag-size' , function ( cb ) {
var $inputBlock = $ ( '<div>' , {
'class' : 'cp-sidebarlayout-input-block' ,
} ) ;
var spinner ;
var $input = $ ( '<input>' , {
'min' : - 1 ,
'max' : 1000 ,
type : 'number' ,
} ) . appendTo ( $inputBlock ) ;
var oldVal ;
var todo = function ( ) {
var val = parseInt ( $input . val ( ) ) ;
if ( typeof ( val ) !== 'number' || isNaN ( val ) ) { return UI . warn ( Messages . error ) ; }
if ( val === oldVal ) { return ; }
spinner . spin ( ) ;
common . setAttribute ( [ 'general' , 'mediatag-size' ] , val , function ( err ) {
if ( err ) {
spinner . hide ( ) ;
console . error ( err ) ;
return UI . warn ( Messages . error ) ;
}
oldVal = val ;
spinner . done ( ) ;
UI . log ( Messages . saved ) ;
} ) ;
} ;
var $save = $ ( h ( 'button.btn.btn-primary' , Messages . settings _save ) ) . appendTo ( $inputBlock ) ;
spinner = UI . makeSpinner ( $inputBlock ) ;
$save . click ( todo ) ;
$input . on ( 'keyup' , function ( e ) {
if ( e . which === 13 ) { todo ( ) ; }
} ) ;
common . getAttribute ( [ 'general' , 'mediatag-size' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( typeof ( val ) !== 'number' || isNaN ( val ) ) {
oldVal = 5 ;
$input . val ( 5 ) ;
} else {
oldVal = val ;
$input . val ( val ) ;
}
} ) ;
cb ( $inputBlock ) ;
} , true ) ;
// Security
makeBlock ( 'safe-links' , function ( cb ) {
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-safe-links' ,
Messages . settings _safeLinksCheckbox ,
false , { label : { class : 'noTitle' } } ) ) ;
var spinner = UI . makeSpinner ( $cbox ) ;
// Checkbox: "Enable safe links"
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
spinner . spin ( ) ;
var val = ! $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'security' , 'unsafeLinks' ] , val , function ( ) {
spinner . done ( ) ;
} ) ;
} ) ;
common . getAttribute ( [ 'security' , 'unsafeLinks' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val === false ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
cb ( $cbox ) ;
} , true ) ;
// Drive settings
create [ 'drive-duplicate' ] = function ( ) {
if ( ! common . isLoggedIn ( ) ) { return ; }
var $div = $ ( '<div>' , {
'class' : 'cp-settings-drive-duplicate cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _driveDuplicateTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _driveDuplicateHint ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-drive-duplicate' ,
Messages . settings _driveDuplicateLabel ,
false , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'drive' , 'hideDuplicate' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
common . getAttribute ( [ 'drive' , 'hideDuplicate' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
return $div ;
} ;
create [ 'resettips' ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-resettips cp-sidebarlayout-element' } ) ;
$ ( '<label>' ) . text ( Messages . settings _resetTips ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _resetTipsButton ) . appendTo ( $div ) ;
var $button = $ ( '<button>' , { 'id' : 'cp-settings-resettips' , 'class' : 'btn btn-primary' } )
. text ( Messages . settings _resetTipsAction ) . appendTo ( $div ) ;
var localStore = window . cryptpadStore ;
$button . click ( function ( ) {
Object . keys ( localStore . store ) . forEach ( function ( k ) {
if ( /^(hide-(info|alert))/ . test ( k ) ) {
localStore . put ( k , null ) ;
}
} ) ;
UI . alert ( Messages . settings _resetTipsDone ) ;
} ) ;
return $div ;
} ;
create [ 'thumbnails' ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-thumbnails cp-sidebarlayout-element' } ) ;
$ ( '<label>' ) . text ( Messages . settings _thumbnails ) . appendTo ( $div ) ;
// Disable
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _disableThumbnailsDescription ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var $cbox = $ ( UI . createCheckbox ( 'disableThumbnails' ,
Messages . settings _disableThumbnailsAction ,
false , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) || false ;
common . setAttribute ( [ 'general' , 'disableThumbnails' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
common . getAttribute ( [ 'general' , 'disableThumbnails' ] , function ( e , val ) {
$checkbox [ 0 ] . checked = typeof ( val ) === "undefined" || val ;
} ) ;
// Reset
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _resetThumbnailsDescription ) . appendTo ( $div ) ;
var $button = $ ( '<button>' , { 'id' : 'resetThumbnails' , 'class' : 'btn btn-primary' } )
. text ( Messages . settings _resetThumbnailsAction ) . appendTo ( $div ) ;
$button . click ( function ( ) {
sframeChan . query ( "Q_THUMBNAIL_CLEAR" , null , function ( err ) {
if ( err ) { return void console . error ( "Cannot clear localForage" ) ; }
UI . alert ( Messages . settings _resetThumbnailsDone ) ;
} ) ;
} ) ;
return $div ;
} ;
create [ 'drive-backup' ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-drive-backup cp-sidebarlayout-element' } ) ;
var accountName = privateData . accountName ;
var displayName = metadataMgr . getUserData ( ) . name || '' ;
var name = displayName || accountName || Messages . anonymous ;
var suggestion = name + '-' + new Date ( ) . toDateString ( ) ;
var exportFile = function ( ) {
sframeChan . query ( "Q_SETTINGS_DRIVE_GET" , null , function ( err , data ) {
if ( err ) { return void console . error ( err ) ; }
var sjson = JSON . stringify ( data ) ;
UI . prompt ( Messages . exportPrompt ,
Util . fixFileName ( suggestion ) + '.json' ,
function ( filename ) {
if ( ! ( typeof ( filename ) === 'string' && filename ) ) { return ; }
var blob = new Blob ( [ sjson ] , { type : "application/json;charset=utf-8" } ) ;
saveAs ( blob , filename ) ;
} ) ;
} ) ;
} ;
var importFile = function ( content ) {
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) . appendTo ( $div ) ;
try {
var data = JSON . parse ( content ) ;
sframeChan . query ( "Q_SETTINGS_DRIVE_SET" , data , function ( e ) {
if ( e ) { console . error ( e ) ; }
$spinner . remove ( ) ;
} ) ;
} catch ( e ) {
console . error ( e ) ;
}
} ;
$ ( '<label>' , { 'for' : 'exportDrive' } ) . text ( Messages . settings _backupCategory ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _backupHint || Messages . settings _backupTitle ) . appendTo ( $div ) ;
/* add an export button */
var $export = common . createButton ( 'export' , true , { } , exportFile ) ;
$export . attr ( 'class' , 'btn btn-success' ) . text ( Messages . settings _backup ) ;
$div . append ( $export ) ;
/* add an import button */
var $import = common . createButton ( 'import' , true , { } , importFile ) ;
$import . attr ( 'class' , 'btn btn-success' ) . text ( Messages . settings _restore ) ;
$div . append ( $import ) ;
// Backup all the pads
var exportDrive = function ( ) {
Feedback . send ( 'FULL_DRIVE_EXPORT_START' ) ;
var todo = function ( data , filename ) {
var ui = Backup . createExportUI ( privateData . origin ) ;
var bu = Backup . create ( data , common . getPad , privateData . fileHost , function ( blob , errors ) {
saveAs ( blob , filename ) ;
sframeChan . event ( 'EV_CRYPTGET_DISCONNECT' ) ;
ui . complete ( function ( ) {
Feedback . send ( 'FULL_DRIVE_EXPORT_COMPLETE' ) ;
saveAs ( blob , filename ) ;
} , errors ) ;
} , ui . update , common . getCache ( ) ) ;
ui . onCancel ( function ( ) {
ui . close ( ) ;
bu . stop ( ) ;
} ) ;
} ;
sframeChan . query ( "Q_SETTINGS_DRIVE_GET" , "full" , function ( err , data ) {
if ( err ) { return void console . error ( err ) ; }
if ( data . error ) { return void console . error ( data . error ) ; }
UI . prompt ( Messages . settings _backup2Confirm ,
Util . fixFileName ( suggestion ) + '.zip' ,
function ( filename ) {
if ( ! ( typeof ( filename ) === 'string' && filename ) ) { return ; }
todo ( data , filename ) ;
} ) ;
} ) ;
} ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _backupHint2 ) . appendTo ( $div ) ;
var $export2 = common . createButton ( 'export' , true , { } , exportDrive ) ;
$export2 . attr ( 'class' , 'btn btn-success' ) . text ( Messages . settings _backup2 ) ;
$div . append ( $export2 ) ;
return $div ;
} ;
create [ 'drive-import-local' ] = function ( ) {
if ( ! common . isLoggedIn ( ) ) { return ; }
var $div = $ ( '<div>' , { 'class' : 'cp-settings-drive-import-local cp-sidebarlayout-element' } ) ;
$ ( '<label>' ) . text ( Messages . settings _import ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _importTitle ) . appendTo ( $div ) ;
var $button = $ ( '<button>' , {
'id' : 'cp-settings-import-local-pads' ,
'class' : 'btn btn-primary'
} ) . text ( Messages . settings _import ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) . hide ( ) . appendTo ( $div ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) . hide ( ) . appendTo ( $div ) ;
$button . click ( function ( ) {
UI . confirm ( Messages . settings _importConfirm , function ( yes ) {
if ( ! yes ) { return ; }
$spinner . show ( ) ;
$ok . hide ( ) ;
sframeChan . query ( 'Q_SETTINGS_IMPORT_LOCAL' , null , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
UI . alert ( Messages . settings _importDone ) ;
} ) ;
} , undefined , true ) ;
} ) ;
return $div ;
} ;
var redrawTrimHistory = function ( cb , $div ) {
var spinner = UI . makeSpinner ( ) ;
var button = h ( 'button.btn.btn-danger-alt' , {
disabled : 'disabled'
} , Messages . trimHistory _button ) ;
var currentSize = h ( 'p' , $ ( spinner . spinner ) . clone ( ) [ 0 ] ) ;
var content = h ( 'div#cp-settings-trim-container' , [
currentSize ,
button ,
spinner . ok ,
spinner . spinner
] ) ;
if ( ! privateData . isDriveOwned ) {
var href = privateData . origin + privateData . pathname + '#' + 'account' ;
$ ( currentSize ) . html ( Messages . trimHistory _needMigration ) ;
$ ( currentSize ) . find ( 'a' ) . prop ( 'href' , href ) . click ( function ( e ) {
e . preventDefault ( ) ;
$ ( '.cp-sidebarlayout-category[data-category="account"]' ) . click ( ) ;
} ) ;
return void cb ( content ) ;
}
var $button = $ ( button ) ;
var size ;
var channels = [ ] ;
nThen ( function ( waitFor ) {
APP . history . execCommand ( 'GET_HISTORY_SIZE' , {
account : true ,
channels : [ ]
} , waitFor ( function ( obj ) {
if ( obj && obj . error ) {
waitFor . abort ( ) ;
var error = h ( 'div.alert.alert-danger' , Messages . trimHistory _getSizeError ) ;
$ ( content ) . empty ( ) . append ( error ) ;
return ;
}
channels = obj . channels ;
size = Number ( obj . size ) ;
} ) ) ;
} ) . nThen ( function ( ) {
if ( ! size || size < 1024 ) {
$ ( currentSize ) . html ( Messages . trimHistory _noHistory ) ;
return ;
}
$ ( currentSize ) . html ( Messages . _getKey ( 'trimHistory_currentSize' , [ UIElements . prettySize ( size ) ] ) ) ;
$button . prop ( 'disabled' , '' ) ;
UI . confirmButton ( button , {
classes : 'btn-danger'
} , function ( ) {
$button . remove ( ) ;
spinner . spin ( ) ;
APP . history . execCommand ( 'TRIM_HISTORY' , {
channels : channels
} , function ( obj ) {
if ( obj && obj . error ) {
var error = h ( 'div.alert.alert-danger' , Messages . trimHistory _error ) ;
$ ( content ) . empty ( ) . append ( error ) ;
return ;
}
spinner . hide ( ) ;
redrawTrimHistory ( cb , $div ) ;
} ) ;
} ) ;
} ) ;
$div . find ( '#cp-settings-trim-container' ) . remove ( ) ;
cb ( content ) ;
} ;
makeBlock ( 'trim-history' , function ( cb , $div ) {
if ( ! common . isLoggedIn ( ) ) { return void cb ( false ) ; }
redrawTrimHistory ( cb , $div ) ;
} , true ) ;
/ *
create [ 'drive-reset' ] = function ( ) {
var $div = $ ( '<div>' , { 'class' : 'cp-settings-drive-reset cp-sidebarlayout-element' } ) ;
$ ( '<label>' ) . text ( Messages . settings _resetNewTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _reset ) . appendTo ( $div ) ;
var $button = $ ( '<button>' , { 'id' : 'cp-settings-reset-drive' , 'class' : 'btn btn-danger' } )
. text ( Messages . settings _resetButton ) . appendTo ( $div ) ;
$button . click ( function ( ) {
UI . prompt ( Messages . settings _resetPrompt , "" , function ( val ) {
if ( val !== "I love CryptPad" ) {
UI . alert ( Messages . settings _resetError ) ;
return ;
}
sframeChan . query ( "Q_SETTINGS_DRIVE_RESET" , null , function ( err ) {
if ( err ) { return void console . error ( err ) ; }
UI . alert ( Messages . settings _resetDone ) ;
} ) ;
} , undefined , true ) ;
} ) ;
return $div ;
} ;
* /
// Cursor settings
create [ 'cursor-color' ] = function ( ) {
var $div = $ ( '<div>' , {
'class' : 'cp-settings-cursor-color cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _cursorColorTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _cursorColorHint ) . appendTo ( $div ) ;
var $inputBlock = $ ( '<div>' ) . appendTo ( $div ) ;
var $colorPicker = $ ( "<div>" , { class : "cp-settings-cursor-color-picker" } ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
// when jscolor picker value change
var _onchange = function ( colorL ) {
var val = "#" + colorL . toString ( ) ;
if ( ! /^#[0-9a-fA-F]{6}$/ . test ( val ) ) { return ; }
common . setAttribute ( [ 'general' , 'cursor' , 'color' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ;
var to ;
var onchange = function ( colorL ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
if ( to ) { clearTimeout ( to ) ; }
to = setTimeout ( function ( ) {
_onchange ( colorL ) ;
} , 300 ) ;
} ;
// jscolor picker
var jscolorL = new window . jscolor ( $colorPicker [ 0 ] , { showOnClick : false , onFineChange : onchange , valueElement : undefined } ) ;
$colorPicker . click ( function ( ) {
jscolorL . show ( ) ;
} ) ;
// set default color
common . getAttribute ( [ 'general' , 'cursor' , 'color' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
val = val || "#000" ;
jscolorL . fromString ( val ) ;
} ) ;
$colorPicker . appendTo ( $inputBlock ) ;
$ok . hide ( ) . appendTo ( $inputBlock ) ;
$spinner . hide ( ) . appendTo ( $inputBlock ) ;
return $div ;
} ;
create [ 'cursor-share' ] = function ( ) {
var $div = $ ( '<div>' , {
'class' : 'cp-settings-cursor-share cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _cursorShareTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _cursorShareHint ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-cursor-share' ,
Messages . settings _cursorShareLabel ,
false , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'general' , 'cursor' , 'share' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
common . getAttribute ( [ 'general' , 'cursor' , 'share' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val !== false ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
return $div ;
} ;
create [ 'cursor-show' ] = function ( ) {
var $div = $ ( '<div>' , {
'class' : 'cp-settings-cursor-show cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _cursorShowTitle + ' (BETA)' ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _cursorShowHint ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-cursor-show' ,
Messages . settings _cursorShowLabel ,
false , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'general' , 'cursor' , 'show' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
common . getAttribute ( [ 'general' , 'cursor' , 'show' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val !== false ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
return $div ;
} ;
// Rich text pads settings
create [ 'pad-width' ] = function ( ) {
var $div = $ ( '<div>' , {
'class' : 'cp-settings-pad-width cp-sidebarlayout-element'
} ) ;
$ ( '<span>' , { 'class' : 'label' } ) . text ( Messages . settings _padWidth ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _padWidthHint ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-padwidth' ,
Messages . settings _padWidthLabel ,
false , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'pad' , 'width' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
common . getAttribute ( [ 'pad' , 'width' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
return $div ;
} ;
create [ 'pad-spellcheck' ] = function ( ) {
var $div = $ ( '<div>' , {
'class' : 'cp-settings-pad-spellcheck cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _padSpellcheckTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _padSpellcheckHint ) . appendTo ( $div ) ;
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-pad-spellcheck' ,
Messages . settings _padSpellcheckLabel ,
false , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'pad' , 'spellcheck' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
common . getAttribute ( [ 'pad' , 'spellcheck' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
return $div ;
} ;
makeBlock ( 'pad-notif' , function ( cb ) {
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-pad-notif' ,
Messages . settings _padNotifCheckbox ,
false , { label : { class : 'noTitle' } } ) ) ;
var spinner = UI . makeSpinner ( $cbox ) ;
// Checkbox: "Enable safe links"
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
spinner . spin ( ) ;
var val = $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'pad' , 'disableNotif' ] , val , function ( ) {
spinner . done ( ) ;
} ) ;
} ) ;
common . getAttribute ( [ 'pad' , 'disableNotif' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val === true ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
cb ( $cbox ) ;
} , true ) ;
// Code settings
create [ 'code-indent-unit' ] = function ( ) {
var $div = $ ( '<div>' , {
'class' : 'cp-settings-code-indent-unit cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _codeIndentation ) . appendTo ( $div ) ;
var $inputBlock = $ ( '<div>' , {
'class' : 'cp-sidebarlayout-input-block' ,
} ) . appendTo ( $div ) ;
var $input = $ ( '<input>' , {
'min' : 1 ,
'max' : 8 ,
type : 'number' ,
} ) . on ( 'change' , function ( ) {
var val = parseInt ( $input . val ( ) ) ;
if ( typeof ( val ) !== 'number' ) { return ; }
common . setAttribute ( [ 'codemirror' , 'indentUnit' ] , val ) ;
} ) . appendTo ( $inputBlock ) ;
common . getAttribute ( [ 'codemirror' , 'indentUnit' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( typeof ( val ) !== 'number' ) {
$input . val ( 2 ) ;
} else {
$input . val ( val ) ;
}
} ) ;
return $div ;
} ;
create [ 'code-indent-type' ] = function ( ) {
var key = 'indentWithTabs' ;
var $div = $ ( '<div>' , {
'class' : 'cp-settings-code-indent-type cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _codeUseTabs ) . appendTo ( $div ) ;
var $inputBlock = $ ( '<div>' , {
'class' : 'cp-sidebarlayout-input-block' ,
} ) . css ( 'flex-flow' , 'column' )
. appendTo ( $div ) ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-codeindent' ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
var val = $checkbox . is ( ':checked' ) ;
if ( typeof ( val ) !== 'boolean' ) { return ; }
common . setAttribute ( [ 'codemirror' , key ] , val ) ;
} ) ;
$cbox . appendTo ( $inputBlock ) ;
/ * p r o x y . o n ( ' c h a n g e ' , [ ' s e t t i n g s ' , ' c o d e m i r r o r ' , k e y ] , f u n c t i o n ( o , n ) {
$input [ 0 ] . checked = ! ! n ;
} ) ; * /
common . getAttribute ( [ 'codemirror' , key ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
$checkbox [ 0 ] . checked = ! ! val ;
} ) ;
return $div ;
} ;
create [ 'code-brackets' ] = function ( ) {
var key = 'brackets' ;
var $div = $ ( '<div>' , {
'class' : 'cp-settings-code-brackets cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _codeBrackets ) . appendTo ( $div ) ;
var $inputBlock = $ ( '<div>' , {
'class' : 'cp-sidebarlayout-input-block' ,
} ) . css ( 'flex-flow' , 'column' )
. appendTo ( $div ) ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-codebrackets' ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
var val = $checkbox . is ( ':checked' ) ;
if ( typeof ( val ) !== 'boolean' ) { return ; }
common . setAttribute ( [ 'codemirror' , key ] , val ) ;
} ) ;
$cbox . appendTo ( $inputBlock ) ;
common . getAttribute ( [ 'codemirror' , key ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
$checkbox [ 0 ] . checked = typeof ( val ) !== "boolean" || val ;
} ) ;
return $div ;
} ;
create [ 'code-font-size' ] = function ( ) {
var key = 'fontSize' ;
var $div = $ ( '<div>' , {
'class' : 'cp-settings-code-font-size cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _codeFontSize ) . appendTo ( $div ) ;
var $inputBlock = $ ( '<div>' , {
'class' : 'cp-sidebarlayout-input-block' ,
} ) . appendTo ( $div ) ;
var $input = $ ( '<input>' , {
'min' : 8 ,
'max' : 30 ,
type : 'number' ,
} ) . on ( 'change' , function ( ) {
var val = parseInt ( $input . val ( ) ) ;
if ( typeof ( val ) !== 'number' ) { return ; }
common . setAttribute ( [ 'codemirror' , key ] , val ) ;
} ) . appendTo ( $inputBlock ) ;
common . getAttribute ( [ 'codemirror' , key ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( typeof ( val ) !== 'number' ) {
$input . val ( 12 ) ;
} else {
$input . val ( val ) ;
}
} ) ;
return $div ;
} ;
create [ 'code-spellcheck' ] = function ( ) {
var $div = $ ( '<div>' , {
'class' : 'cp-settings-code-spellcheck cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _codeSpellcheckTitle ) . appendTo ( $div ) ;
//$('<span>', {'class': 'cp-sidebarlayout-description'})
// .text(Messages.settings_padSpellcheckHint).appendTo($div);
var $ok = $ ( '<span>' , { 'class' : 'fa fa-check' , title : Messages . saved } ) ;
var $spinner = $ ( '<span>' , { 'class' : 'fa fa-spinner fa-pulse' } ) ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-code-spellcheck' ,
Messages . settings _codeSpellcheckLabel ,
false , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'codemirror' , 'spellcheck' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
common . getAttribute ( [ 'codemirror' , 'spellcheck' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
return $div ;
} ;
makeBlock ( 'kanban-tags' , function ( cb ) {
var opt1 = UI . createRadio ( 'cp-settings-kanban-tags' , 'cp-settings-kanban-tags-and' ,
Messages . settings _kanbanTagsAnd , false , {
input : { value : 1 } ,
label : { class : 'noTitle' }
} ) ;
var opt2 = UI . createRadio ( 'cp-settings-kanban-tags' , 'cp-settings-kanban-tags-or' ,
Messages . settings _kanbanTagsOr , true , {
input : { value : 0 } ,
label : { class : 'noTitle' }
} ) ;
var div = h ( 'div.cp-settings-radio-container' , [
opt1 ,
opt2 ,
] ) ;
var $d = $ ( div ) ;
var spinner = UI . makeSpinner ( $d ) ;
$d . find ( 'input[type="radio"]' ) . on ( 'change' , function ( ) {
spinner . spin ( ) ;
var val = $ ( 'input:radio[name="cp-settings-kanban-tags"]:checked' ) . val ( ) ;
val = Number ( val ) || 0 ;
common . setAttribute ( [ 'kanban' , 'tagsAnd' ] , val , function ( ) {
spinner . done ( ) ;
} ) ;
} ) ;
common . getAttribute ( [ 'kanban' , 'tagsAnd' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val ) {
$ ( opt1 ) . find ( 'input' ) . attr ( 'checked' , 'checked' ) ;
}
} ) ;
cb ( $d ) ;
} , true ) ;
// Settings app
var createUsageButton = function ( ) {
common . createUsageBar ( null , function ( err , $bar ) {
if ( err ) { return void console . error ( err ) ; }
APP . $usage . html ( '' ) . append ( $bar ) ;
} , true ) ;
} ;
var hideCategories = function ( ) {
APP . $rightside . find ( '> div' ) . hide ( ) ;
} ;
var showCategories = function ( cat ) {
hideCategories ( ) ;
cat . forEach ( function ( c ) {
APP . $rightside . find ( '.' + c ) . show ( ) ;
} ) ;
} ;
var createLeftside = function ( ) {
var $categories = $ ( '<div>' , { 'class' : 'cp-sidebarlayout-categories' } )
. appendTo ( APP . $leftside ) ;
APP . $usage = $ ( '<div>' , { 'class' : 'usage' } ) . appendTo ( APP . $leftside ) ;
var active = privateData . category || 'account' ;
Object . keys ( categories ) . forEach ( function ( key ) {
var $category = $ ( '<div>' , {
'class' : 'cp-sidebarlayout-category' ,
'data-category' : key
} ) . appendTo ( $categories ) ;
if ( key === 'account' ) { $category . append ( $ ( '<span>' , { 'class' : 'fa fa-user-o' } ) ) ; }
if ( key === 'drive' ) { $category . append ( $ ( '<span>' , { 'class' : 'fa fa-hdd-o' } ) ) ; }
if ( key === 'cursor' ) { $category . append ( $ ( '<span>' , { 'class' : 'fa fa-i-cursor' } ) ) ; }
if ( key === 'code' ) { $category . append ( $ ( '<span>' , { 'class' : 'fa fa-file-code-o' } ) ) ; }
if ( key === 'pad' ) { $category . append ( $ ( '<span>' , { 'class' : 'fa fa-file-word-o' } ) ) ; }
if ( key === 'security' ) { $category . append ( $ ( '<span>' , { 'class' : 'fa fa-lock' } ) ) ; }
if ( key === 'subscription' ) { $category . append ( $ ( '<span>' , { 'class' : 'fa fa-star-o' } ) ) ; }
if ( key === 'kanban' ) { $category . append ( $ ( '<span>' , { 'class' : 'cptools cptools-kanban' } ) ) ; }
if ( key === active ) {
$category . addClass ( 'cp-leftside-active' ) ;
}
$category . click ( function ( ) {
if ( ! Array . isArray ( categories [ key ] ) && categories [ key ] . onClick ) {
categories [ key ] . onClick ( ) ;
return ;
}
active = key ;
common . setHash ( key ) ;
$categories . find ( '.cp-leftside-active' ) . removeClass ( 'cp-leftside-active' ) ;
$category . addClass ( 'cp-leftside-active' ) ;
showCategories ( categories [ key ] ) ;
} ) ;
$category . append ( Messages [ 'settings_cat_' + key ] || key ) ;
} ) ;
showCategories ( categories [ active ] ) ;
common . setHash ( active ) ;
} ;
nThen ( function ( waitFor ) {
$ ( waitFor ( UI . addLoadingScreen ) ) ;
SFCommon . create ( waitFor ( function ( c ) { APP . common = common = c ; } ) ) ;
} ) . nThen ( function ( waitFor ) {
APP . $container = $ ( '#cp-sidebarlayout-container' ) ;
APP . $toolbar = $ ( '#cp-toolbar' ) ;
APP . $leftside = $ ( '<div>' , { id : 'cp-sidebarlayout-leftside' } ) . appendTo ( APP . $container ) ;
APP . $rightside = $ ( '<div>' , { id : 'cp-sidebarlayout-rightside' } ) . appendTo ( APP . $container ) ;
sframeChan = common . getSframeChannel ( ) ;
sframeChan . onReady ( waitFor ( ) ) ;
} ) . nThen ( function ( /*waitFor*/ ) {
metadataMgr = common . getMetadataMgr ( ) ;
privateData = metadataMgr . getPrivateData ( ) ;
// Toolbar
var displayed = [ 'useradmin' , 'newpad' , 'limit' , 'pageTitle' , 'notifications' ] ;
var configTb = {
displayed : displayed ,
sfCommon : common ,
$container : APP . $toolbar ,
pageTitle : Messages . settings _title ,
metadataMgr : common . getMetadataMgr ( ) ,
} ;
APP . toolbar = Toolbar . create ( configTb ) ;
APP . toolbar . $rightside . hide ( ) ;
APP . history = common . makeUniversal ( 'history' ) ;
// Content
var $rightside = APP . $rightside ;
/ * f o r ( v a r f i n c r e a t e ) {
if ( typeof create [ f ] !== "function" ) { continue ; }
$rightside . append ( create [ f ] ( ) ) ;
} * /
var addItem = function ( cssClass ) {
var item = cssClass . slice ( 12 ) ; // remove 'cp-settings-'
if ( typeof ( create [ item ] ) === "function" ) {
$rightside . append ( create [ item ] ( ) ) ;
}
} ;
for ( var cat in categories ) {
if ( ! Array . isArray ( categories [ cat ] ) ) { continue ; }
categories [ cat ] . forEach ( addItem ) ;
}
// TODO RPC
//obj.proxy.on('change', [], refresh);
//obj.proxy.on('remove', [], refresh);
//Cryptpad.onDisplayNameChanged(refresh);
createLeftside ( ) ;
createUsageButton ( ) ;
UI . removeLoadingScreen ( ) ;
} ) ;
} ) ;