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/common-constants.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 ,
Constants
) {
var saveAs = window . saveAs ;
var APP = window . APP = { } ;
var common ;
var metadataMgr ;
var privateData ;
var sframeChan ;
var categories = {
'account' : [ // Msg.settings_cat_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' : [ // Msg.settings_cat_security
'cp-settings-logout-everywhere' ,
'cp-settings-autostore' ,
'cp-settings-safe-links' ,
'cp-settings-userfeedback' ,
'cp-settings-cache' ,
] ,
'style' : [ // Msg.settings_cat_style
'cp-settings-colortheme' ,
'cp-settings-custom-theme' ,
] ,
'drive' : [
'cp-settings-redirect' ,
'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' : [ // Msg.settings_cat_cursor
'cp-settings-cursor-color' ,
'cp-settings-cursor-share' ,
'cp-settings-cursor-show' ,
] ,
'pad' : [ // Msg.settings_cat_pad
'cp-settings-pad-width' ,
'cp-settings-pad-spellcheck' ,
'cp-settings-pad-notif' ,
'cp-settings-pad-openlink' ,
] ,
'code' : [ // Msg.settings_cat_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' : [ // Msg.settings_cat_kanban
'cp-settings-kanban-tags' ,
] ,
'notifications' : [
'cp-settings-notif-calendar'
] ,
'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 ;
} ;
makeBlock ( 'cache' , function ( cb ) { // Msg.settings_cacheHint, .settings_cacheTitle
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 ) ;
makeBlock ( 'colortheme' , function ( cb ) { // Msg.settings_colorthemeHint .settings_colorthemeTitle
var theme = window . cryptpadStore . store [ 'colortheme' ] || 'default' ;
var os = window . cryptpadStore . store [ 'colortheme_default' ] || 'light' ;
var values = [
'default' , // Msg.settings_colortheme_default
'light' , // Msg.settings_colortheme_light
'dark' , // Msg.settings_colortheme_dark
/* 'custom'*/ // Msg.settings_colortheme_custom
] ;
var defaultTheme = Messages [ 'settings_colortheme_' + os ] ;
var opts = h ( 'div.cp-settings-radio-container' , [
values . map ( function ( key ) {
return UI . createRadio ( 'cp-colortheme-radio' , 'cp-colortheme-radio-' + key ,
Messages . _getKey ( 'settings_colortheme_' + key , [ defaultTheme ] ) ,
key === theme , {
input : { value : key } ,
label : { class : 'noTitle' }
} ) ;
} )
] ) ;
cb ( opts ) ;
var spinner = UI . makeSpinner ( $ ( opts ) ) ;
$ ( opts ) . find ( 'input[name="cp-colortheme-radio"]' ) . change ( function ( ) {
var val = this . value ;
if ( values . indexOf ( val ) === - 1 ) { return ; }
if ( val === theme ) { return ; }
spinner . spin ( ) ;
// Check if we need to flush cache
var flush = false ;
if ( val === "default" && os === theme ) {
// Switch from a theme to default without changing value: nothing to do
} else if ( theme === "default" && os === val ) {
// Switch from default to a selected value without any change: nothing to do
} else {
// The theme is different, flush cache
flush = true ;
}
if ( val === 'default' ) { val = '' ; }
// browsers try to load iframes from cache if they have the same id as was previously seen
// this seems to help?
window . location . hash = '' ;
sframeChan . query ( 'Q_COLORTHEME_CHANGE' , {
theme : val ,
flush : flush
} , function ( ) {
window . cryptpadStore . store [ 'colortheme' ] = val ;
theme = val || 'default' ;
spinner . done ( ) ;
} ) ;
} ) ;
} , true ) ;
makeBlock ( 'delete' , function ( cb ) { // Msg.settings_deleteHint, .settings_deleteTitle
if ( ! common . isLoggedIn ( ) ) { return cb ( false ) ; }
var button = h ( 'button.btn.btn-danger' , Messages . settings _deleteButton ) ;
var form = h ( 'div' , [
UI . passwordInput ( {
id : 'cp-settings-delete-account' ,
placeholder : Messages . settings _changePasswordCurrent
} , true ) ,
button
] ) ;
var $form = $ ( form ) ;
var $button = $ ( button ) ;
var spinner = UI . makeSpinner ( $form ) ;
UI . confirmButton ( button , {
classes : 'btn-danger' ,
multiple : true
} , function ( ) {
nThen ( function ( waitFor ) {
$button . prop ( 'disabled' , 'disabled' ) ;
var priv = metadataMgr . getPrivateData ( ) ;
// Check if subscriptions are enabled and you have a premium plan
if ( priv . plan && priv . plan !== "custom" && ApiConfig . allowSubscriptions ) {
// Also make sure upgradeURL is defined
var url = priv . accounts && priv . accounts . upgradeURL ;
if ( ! url ) { return ; }
url += '#mysubs' ;
var a = h ( 'a' , { href : url } , Messages . settings _deleteSubscription ) ;
$ ( a ) . click ( function ( e ) {
e . preventDefault ( ) ;
common . openUnsafeURL ( url ) ;
} ) ;
UI . confirm ( h ( 'div' , [
Messages . settings _deleteWarning , h ( 'p' , a )
] ) , waitFor ( function ( yes ) {
if ( ! yes ) {
$button . prop ( 'disabled' , '' ) ;
waitFor . abort ( ) ;
}
} ) , {
ok : Messages . settings _deleteContinue ,
okClass : 'btn.btn-danger' ,
cancelClass : 'btn.btn-primary'
} ) ;
}
} ) . nThen ( function ( ) {
var password = $form . find ( '#cp-settings-delete-account' ) . val ( ) ;
if ( ! password ) {
return void UI . warn ( Messages . error ) ;
}
spinner . spin ( ) ;
sframeChan . query ( "Q_SETTINGS_DELETE_ACCOUNT" , {
password : password
} , function ( err , data ) {
if ( data && data . error ) {
spinner . hide ( ) ;
$button . prop ( 'disabled' , '' ) ;
if ( data . error === 'INVALID_PASSWORD' ) {
return void UI . warn ( Messages . drive _sfPasswordError ) ;
}
console . error ( data . error ) ;
return void UI . warn ( Messages . error ) ;
}
// Owned drive
if ( data . state === true ) {
sframeChan . query ( 'Q_SETTINGS_LOGOUT' , null , function ( ) { } ) ;
UI . alert ( Messages . settings _deleted , function ( ) {
common . gotoURL ( '/' ) ;
} ) ;
spinner . done ( ) ;
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 ( ) ;
$button . prop ( 'disabled' , '' ) ;
} ) ;
} ) ;
} ) ;
cb ( form ) ;
} , true ) ;
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 ,
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 ) { // Msg.settings_ownDriveHint, .settings_ownDriveTitle
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 ) { // Msg.settings_mediatagSizeHint, .settings_mediatagSizeTitle
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 ) { // Msg.settings_safeLinksTitle
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 ;
} ;
Messages . settings _driveRedirectTitle = "Home page redirection" ; // XXX redirect
Messages . settings _driveRedirectHint = "Automatic redirection from the home page to the drive when logged in is no longer enabled by default. Legacy behaviour can be enabled below." ; // XXX redirect
Messages . settings _driveRedirect = "Automatically redirect me" ; // XXX redirect
create [ 'redirect' ] = function ( ) {
if ( ! common . isLoggedIn ( ) ) { return ; }
var $div = $ ( '<div>' , { 'class' : 'cp-settings-redirect cp-sidebarlayout-element' } ) ;
$ ( '<span>' , { 'class' : 'label' } ) . text ( Messages . settings _driveRedirectTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. append ( Messages . settings _driveRedirectHint )
. 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-redirect' ,
Messages . settings _driveRedirect ,
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' , Constants . prefersDriveRedirectKey ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
sframeChan . query ( "Q_SET_DRIVE_REDIRECT_PREFERENCE" , {
value : val ,
} , console . log ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
if ( privateData . prefersDriveRedirect === true ) {
$checkbox [ 0 ] . checked = true ;
}
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 ) { // Msg.settings_trimHistoryHint, .settings_trimHistoryTitle
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 store = window . cryptpadStore ;
var key = 'pad-small-width' ;
var isHidden = store . store [ key ] === '1' ;
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-padwidth' ,
Messages . settings _padWidthLabel ,
isHidden , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) ;
store . put ( key , val ? '1' : '0' , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
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 ) { // Msg.settings_padNotifHint, .settings_padNotifTitle
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 ) ;
create [ 'pad-openlink' ] = function ( ) {
var $div = $ ( '<div>' , {
'class' : 'cp-settings-pad-openlink cp-sidebarlayout-element'
} ) ;
$ ( '<label>' ) . text ( Messages . settings _padOpenLinkTitle ) . appendTo ( $div ) ;
$ ( '<span>' , { 'class' : 'cp-sidebarlayout-description' } )
. text ( Messages . settings _padOpenLinkHint ) . 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-openlink' ,
Messages . settings _padOpenLinkLabel ,
false , { label : { class : 'noTitle' } } ) ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
$spinner . show ( ) ;
$ok . hide ( ) ;
var val = $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'pad' , 'openLink' ] , val , function ( ) {
$spinner . hide ( ) ;
$ok . show ( ) ;
} ) ;
} ) ;
$cbox . appendTo ( $div ) ;
$ok . hide ( ) . appendTo ( $cbox ) ;
$spinner . hide ( ) . appendTo ( $cbox ) ;
common . getAttribute ( [ 'pad' , 'openLink' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( val ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
return $div ;
} ;
// 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 ) { // Msg.settings_kanbanTagsHint, .settings_kanbanTagsTitle
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 ) ;
makeBlock ( 'notif-calendar' , function ( cb ) { // Msg.settings_notifCalendarHint, .settings_notifCalendarTitle
var $cbox = $ ( UI . createCheckbox ( 'cp-settings-cache' ,
Messages . settings _notifCalendarCheckbox ,
false , { label : { class : 'noTitle' } } ) ) ;
var spinner = UI . makeSpinner ( $cbox ) ;
var $checkbox = $cbox . find ( 'input' ) . on ( 'change' , function ( ) {
spinner . spin ( ) ;
var val = ! $checkbox . is ( ':checked' ) ;
common . setAttribute ( [ 'general' , 'calendar' , 'hideNotif' ] , val , function ( e ) {
if ( e ) {
console . error ( e ) ;
// error: restore previous value
if ( val ) { $checkbox . attr ( 'checked' , '' ) ; }
else { $checkbox . attr ( 'checked' , 'checked' ) ; }
spinner . hide ( ) ;
return void console . error ( e ) ;
}
spinner . done ( ) ;
} ) ;
} ) ;
common . getAttribute ( [ 'general' , 'calendar' , 'hideNotif' ] , function ( e , val ) {
if ( e ) { return void console . error ( e ) ; }
if ( ! val ) {
$checkbox . attr ( 'checked' , 'checked' ) ;
}
} ) ;
cb ( $cbox [ 0 ] ) ;
} , 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 SIDEBAR _ICONS = {
account : 'fa fa-user-o' ,
drive : 'fa fa-hdd-o' ,
cursor : 'fa fa-i-cursor' ,
code : 'fa fa-file-code-o' ,
pad : 'fa fa-file-word-o' ,
security : 'fa fa-lock' ,
subscription : 'fa fa-star-o' ,
kanban : 'cptools cptools-kanban' ,
style : 'cptools cptools-palette' ,
notifications : 'fa fa-bell'
} ;
Messages . settings _cat _notifications = Messages . notificationsPage ;
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' ;
if ( ! categories [ active ] ) { active = 'account' ; }
Object . keys ( categories ) . forEach ( function ( key ) {
var $category = $ ( '<div>' , {
'class' : 'cp-sidebarlayout-category' ,
'data-category' : key
} ) . appendTo ( $categories ) ;
var iconClass = SIDEBAR _ICONS [ key ] ;
if ( iconClass ) {
$category . append ( $ ( '<span>' , { 'class' : iconClass } ) ) ;
}
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 ( ) ;
} ) ;
} ) ;