2017-08-17 14:28:54 +00:00
define ( [
2017-08-23 09:04:44 +00:00
'jquery' ,
2021-03-11 11:27:12 +00:00
'/api/config' ,
2017-08-17 14:56:18 +00:00
'/bower_components/nthen/index.js' ,
2017-08-21 13:20:38 +00:00
'/customize/messages.js' ,
2017-08-17 14:28:54 +00:00
'/common/sframe-chainpad-netflux-inner.js' ,
2019-01-11 14:22:52 +00:00
'/common/outer/worker-channel.js' ,
2017-08-17 17:58:48 +00:00
'/common/sframe-common-title.js' ,
2017-11-09 17:17:49 +00:00
'/common/common-ui-elements.js' ,
2017-08-21 15:40:21 +00:00
'/common/sframe-common-history.js' ,
2017-08-31 14:32:26 +00:00
'/common/sframe-common-file.js' ,
2017-09-07 16:56:58 +00:00
'/common/sframe-common-codemirror.js' ,
2018-12-04 16:18:42 +00:00
'/common/sframe-common-cursor.js' ,
2019-05-15 16:22:39 +00:00
'/common/sframe-common-mailbox.js' ,
2020-11-27 16:11:12 +00:00
'/common/inner/cache.js' ,
2020-03-30 10:09:12 +00:00
'/common/inner/common-mediatag.js' ,
2017-08-17 17:58:48 +00:00
'/common/metadata-manager.js' ,
2017-08-17 16:28:05 +00:00
2017-08-21 16:30:51 +00:00
'/customize/application_config.js' ,
2021-03-24 09:11:47 +00:00
'/customize/pages.js' ,
2017-09-11 13:46:21 +00:00
'/common/common-realtime.js' ,
2017-11-06 12:36:54 +00:00
'/common/common-util.js' ,
2017-11-13 15:32:40 +00:00
'/common/common-hash.js' ,
2017-11-07 13:51:53 +00:00
'/common/common-thumbnail.js' ,
2017-11-13 09:23:18 +00:00
'/common/common-interface.js' ,
2017-11-23 11:28:49 +00:00
'/common/common-feedback.js' ,
2017-12-07 11:20:26 +00:00
'/common/common-language.js' ,
2021-03-24 09:11:47 +00:00
'/bower_components/localforage/dist/localforage.min.js' ,
'/common/hyperscript.js' ,
2017-09-11 13:52:14 +00:00
] , function (
$ ,
2021-03-11 11:27:12 +00:00
ApiConfig ,
2017-09-11 13:52:14 +00:00
nThen ,
Messages ,
CpNfInner ,
SFrameChannel ,
Title ,
2017-11-13 09:23:18 +00:00
UIElements ,
2017-09-11 13:52:14 +00:00
History ,
File ,
CodeMirror ,
2018-12-04 16:18:42 +00:00
Cursor ,
2019-05-15 16:22:39 +00:00
Mailbox ,
2020-11-27 16:11:12 +00:00
Cache ,
2020-03-30 10:09:12 +00:00
MT ,
2017-09-07 16:56:58 +00:00
MetadataMgr ,
2017-09-11 13:52:14 +00:00
AppConfig ,
2021-03-24 09:11:47 +00:00
Pages ,
2017-09-11 13:52:14 +00:00
CommonRealtime ,
2017-11-06 12:36:54 +00:00
Util ,
2017-11-13 15:32:40 +00:00
Hash ,
2017-11-07 13:51:53 +00:00
Thumb ,
2017-11-13 09:23:18 +00:00
UI ,
2017-11-23 11:28:49 +00:00
Feedback ,
2017-12-07 11:20:26 +00:00
Language ,
2021-03-24 09:11:47 +00:00
localForage ,
h
2017-09-11 13:52:14 +00:00
) {
2017-08-17 14:28:54 +00:00
// Chainpad Netflux Inner
2017-08-17 14:56:18 +00:00
var funcs = { } ;
var ctx = { } ;
2017-08-21 15:40:21 +00:00
funcs . Messages = Messages ;
2017-09-11 13:46:21 +00:00
var evRealtimeSynced = Util . mkEvent ( true ) ;
2017-08-17 14:56:18 +00:00
funcs . startRealtime = function ( options ) {
if ( ctx . cpNfInner ) { return ctx . cpNfInner ; }
options . sframeChan = ctx . sframeChan ;
2017-08-17 17:58:48 +00:00
options . metadataMgr = ctx . metadataMgr ;
2017-08-17 14:56:18 +00:00
ctx . cpNfInner = CpNfInner . start ( options ) ;
2017-08-17 17:01:33 +00:00
ctx . cpNfInner . metadataMgr . onChangeLazy ( options . onLocal ) ;
2017-09-11 13:46:21 +00:00
ctx . cpNfInner . whenRealtimeSyncs ( function ( ) { evRealtimeSynced . fire ( ) ; } ) ;
2017-08-17 14:56:18 +00:00
return ctx . cpNfInner ;
} ;
2017-09-06 16:26:10 +00:00
funcs . getMetadataMgr = function ( ) { return ctx . metadataMgr ; } ;
funcs . getSframeChannel = function ( ) { return ctx . sframeChan ; } ;
funcs . getAppConfig = function ( ) { return AppConfig ; } ;
2017-08-21 15:40:21 +00:00
2017-09-07 16:56:58 +00:00
funcs . isLoggedIn = function ( ) {
2020-02-28 14:48:50 +00:00
return ctx . metadataMgr . getPrivateData ( ) . loggedIn ;
2017-08-17 14:28:54 +00:00
} ;
2017-09-06 16:26:10 +00:00
// MISC
// Call the selected function with 'funcs' as a (new) first parameter
var callWithCommon = function ( f ) {
return function ( ) {
[ ] . unshift . call ( arguments , funcs ) ;
return f . apply ( null , arguments ) ;
} ;
} ;
2017-08-18 14:34:41 +00:00
// UI
2020-02-03 14:14:52 +00:00
window . CryptPad _UI = UI ;
window . CryptPad _UIElements = UIElements ;
window . CryptPad _common = funcs ;
2017-11-13 09:23:18 +00:00
funcs . createUserAdminMenu = callWithCommon ( UIElements . createUserAdminMenu ) ;
funcs . openFilePicker = callWithCommon ( UIElements . openFilePicker ) ;
funcs . openTemplatePicker = callWithCommon ( UIElements . openTemplatePicker ) ;
2020-03-30 10:09:12 +00:00
funcs . displayMediatagImage = callWithCommon ( MT . displayMediatagImage ) ;
funcs . displayAvatar = callWithCommon ( MT . displayAvatar ) ;
2017-11-13 09:23:18 +00:00
funcs . createButton = callWithCommon ( UIElements . createButton ) ;
funcs . createUsageBar = callWithCommon ( UIElements . createUsageBar ) ;
funcs . updateTags = callWithCommon ( UIElements . updateTags ) ;
funcs . createLanguageSelector = callWithCommon ( UIElements . createLanguageSelector ) ;
2017-11-27 11:17:35 +00:00
funcs . createMarkdownToolbar = callWithCommon ( UIElements . createMarkdownToolbar ) ;
2018-02-27 16:38:29 +00:00
funcs . createHelpMenu = callWithCommon ( UIElements . createHelpMenu ) ;
2017-12-07 17:51:50 +00:00
funcs . getPadCreationScreen = callWithCommon ( UIElements . getPadCreationScreen ) ;
2020-01-09 16:30:15 +00:00
funcs . getBurnAfterReadingWarning = callWithCommon ( UIElements . getBurnAfterReadingWarning ) ;
2018-01-12 08:48:40 +00:00
funcs . createNewPadModal = callWithCommon ( UIElements . createNewPadModal ) ;
2018-02-15 10:34:44 +00:00
funcs . onServerError = callWithCommon ( UIElements . onServerError ) ;
2020-04-28 13:54:12 +00:00
funcs . addMentions = callWithCommon ( UIElements . addMentions ) ;
2020-03-31 14:43:00 +00:00
funcs . importMediaTagMenu = callWithCommon ( MT . importMediaTagMenu ) ;
funcs . getMediaTagPreview = callWithCommon ( MT . getMediaTagPreview ) ;
2020-06-04 09:47:15 +00:00
funcs . getMediaTag = callWithCommon ( MT . getMediaTag ) ;
2017-11-06 12:36:54 +00:00
// Thumb
2017-11-07 13:51:53 +00:00
funcs . displayThumbnail = callWithCommon ( Thumb . displayThumbnail ) ;
2018-03-13 10:31:08 +00:00
funcs . addThumbnail = Thumb . addThumbnail ;
2017-08-18 14:34:41 +00:00
2017-08-21 15:40:21 +00:00
// History
2017-09-06 16:26:10 +00:00
funcs . getHistory = callWithCommon ( History . create ) ;
2017-08-21 15:40:21 +00:00
2017-08-17 16:28:05 +00:00
// Title module
2017-09-06 16:26:10 +00:00
funcs . createTitle = callWithCommon ( Title . create ) ;
2018-12-04 16:18:42 +00:00
// Cursor
funcs . createCursor = callWithCommon ( Cursor . create ) ;
2017-09-06 16:26:10 +00:00
// Files
funcs . uploadFile = callWithCommon ( File . uploadFile ) ;
funcs . createFileManager = callWithCommon ( File . create ) ;
2017-09-12 16:40:11 +00:00
funcs . getMediatagScript = function ( ) {
var origin = ctx . metadataMgr . getPrivateData ( ) . origin ;
return '<script src="' + origin + '/common/media-tag-nacl.min.js"></script>' ;
} ;
2018-08-23 10:34:44 +00:00
funcs . getMediatagFromHref = function ( obj ) {
2019-05-29 17:00:20 +00:00
if ( ! obj || ! obj . hash ) { return ; }
2017-09-12 16:40:11 +00:00
var data = ctx . metadataMgr . getPrivateData ( ) ;
2019-05-29 17:00:20 +00:00
var secret = Hash . getSecrets ( 'file' , obj . hash , obj . password ) ;
2017-09-12 16:40:11 +00:00
if ( secret . keys && secret . channel ) {
2018-05-25 16:00:10 +00:00
var key = Hash . encodeBase64 ( secret . keys && secret . keys . cryptKey ) ;
var hexFileName = secret . channel ;
2017-09-12 16:40:11 +00:00
var origin = data . fileHost || data . origin ;
2017-11-13 15:32:40 +00:00
var src = origin + Hash . getBlobPathFromHex ( hexFileName ) ;
2021-07-01 07:38:35 +00:00
return UI . mediaTag ( src , key ) . outerHTML ;
2017-09-12 16:40:11 +00:00
}
return ;
} ;
2020-11-25 14:51:22 +00:00
var getMtData = function ( $mt ) {
2018-08-31 13:41:08 +00:00
if ( ! $mt || ! $mt . is ( 'media-tag' ) ) { return ; }
var chanStr = $mt . attr ( 'src' ) ;
var keyStr = $mt . attr ( 'data-crypto-key' ) ;
2020-02-07 12:36:54 +00:00
// Remove origin
var a = document . createElement ( 'a' ) ;
a . href = chanStr ;
var src = a . pathname ;
// Get channel id
var channel = src . replace ( /\/blob\/[0-9a-f]{2}\//i , '' ) ;
// Get key
2018-08-31 13:41:08 +00:00
var key = keyStr . replace ( /cryptpad:/i , '' ) ;
2020-11-25 14:51:22 +00:00
return {
channel : channel ,
key : key
} ;
} ;
funcs . getHashFromMediaTag = function ( $mt ) {
var data = getMtData ( $mt ) ;
if ( ! data ) { return ; }
return Hash . getFileHashFromKeys ( {
version : 1 ,
channel : data . channel ,
keys : { fileKeyStr : data . key }
} ) ;
} ;
funcs . importMediaTag = function ( $mt ) {
var data = getMtData ( $mt ) ;
if ( ! data ) { return ; }
2018-08-31 13:41:08 +00:00
var metadata = $mt [ 0 ] . _mediaObject . _blob . metadata ;
ctx . sframeChan . query ( 'Q_IMPORT_MEDIATAG' , {
2020-11-25 14:51:22 +00:00
channel : data . channel ,
key : data . key ,
2018-08-31 13:41:08 +00:00
name : metadata . name ,
type : metadata . type ,
owners : metadata . owners
} , function ( ) {
UI . log ( Messages . saved ) ;
} ) ;
} ;
2021-01-11 10:48:56 +00:00
funcs . getFileSize = function ( channelId , cb , noCache ) {
2020-11-06 16:13:41 +00:00
nThen ( function ( waitFor ) {
2021-01-11 10:48:56 +00:00
if ( channelId . length < 48 || noCache ) { return ; }
2021-01-07 11:47:17 +00:00
ctx . cache . getBlobCache ( channelId , waitFor ( function ( err , blob ) {
2020-11-06 16:13:41 +00:00
if ( err ) { return ; }
waitFor . abort ( ) ;
cb ( null , blob . length ) ;
} ) ) ;
} ) . nThen ( function ( ) {
funcs . sendAnonRpcMsg ( "GET_FILE_SIZE" , channelId , function ( data ) {
if ( ! data ) { return void cb ( "No response" ) ; }
if ( data . error ) { return void cb ( data . error ) ; }
if ( data . response && data . response . length && typeof ( data . response [ 0 ] ) === 'number' ) {
return void cb ( void 0 , data . response [ 0 ] ) ;
} else {
cb ( 'INVALID_RESPONSE' ) ;
}
} ) ;
2017-09-13 14:19:26 +00:00
} ) ;
} ;
2019-05-24 15:45:03 +00:00
// Universal direct channel
var modules = { } ;
funcs . makeUniversal = function ( type , cfg ) {
2019-09-20 13:27:20 +00:00
if ( cfg && cfg . onEvent ) {
2021-03-30 13:18:58 +00:00
modules [ type ] = modules [ type ] || Util . mkEvent ( ) ;
modules [ type ] . reg ( cfg . onEvent ) ;
2019-09-20 13:27:20 +00:00
}
2019-09-18 11:30:24 +00:00
var sframeChan = funcs . getSframeChannel ( ) ;
2019-05-24 15:45:03 +00:00
return {
execCommand : function ( cmd , data , cb ) {
sframeChan . query ( "Q_UNIVERSAL_COMMAND" , {
type : type ,
data : {
cmd : cmd ,
data : data
}
} , function ( err , obj ) {
if ( err ) { return void cb ( { error : err } ) ; }
cb ( obj ) ;
} ) ;
}
} ;
} ;
2020-05-28 10:39:36 +00:00
funcs . getAuthorId = function ( ) {
} ;
var authorUid = function ( existing ) {
if ( ! Array . isArray ( existing ) ) { existing = [ ] ; }
var n ;
var i = 0 ;
while ( ! n || existing . indexOf ( n ) !== - 1 && i ++ < 1000 ) {
n = Math . floor ( Math . random ( ) * 1000000 ) ;
}
// If we can't find a valid number in 1000 iterations, use 0...
if ( existing . indexOf ( n ) !== - 1 ) { n = 0 ; }
return n ;
} ;
funcs . getAuthorId = function ( authors , curve ) {
var existing = Object . keys ( authors || { } ) . map ( Number ) ;
if ( ! funcs . isLoggedIn ( ) ) { return authorUid ( existing ) ; }
var uid ;
existing . some ( function ( id ) {
var author = authors [ id ] || { } ;
if ( author . curvePublic !== curve ) { return ; }
uid = Number ( id ) ;
return true ;
} ) ;
return uid || authorUid ( existing ) ;
} ;
2019-05-24 15:45:03 +00:00
2018-09-07 17:35:06 +00:00
// Chat
2018-09-10 15:43:19 +00:00
var padChatChannel ;
2018-12-12 12:48:28 +00:00
// common-ui-elements needs to be able to get the chat channel to put it in metadata when
// importing a template
2018-09-10 15:43:19 +00:00
funcs . getPadChat = function ( ) {
return padChatChannel ;
} ;
2018-09-07 17:35:06 +00:00
funcs . openPadChat = function ( saveChanges ) {
var md = JSON . parse ( JSON . stringify ( ctx . metadataMgr . getMetadata ( ) ) ) ;
2018-12-11 12:35:00 +00:00
//if (md.chat) { delete md.chat; } // Old channel without signing key
2018-12-12 12:48:28 +00:00
// NOTE: "chat2" is also used in cryptpad-common's "useTemplate"
2018-12-10 16:47:47 +00:00
var channel = md . chat2 || Hash . createChannelId ( ) ;
if ( ! md . chat2 ) {
md . chat2 = channel ;
2018-09-07 17:35:06 +00:00
ctx . metadataMgr . updateMetadata ( md ) ;
setTimeout ( saveChanges ) ;
}
2018-09-10 15:43:19 +00:00
padChatChannel = channel ;
2020-06-29 20:51:28 +00:00
console . debug ( 'Chat ID:' , channel ) ;
2018-09-07 17:35:06 +00:00
ctx . sframeChan . query ( 'Q_CHAT_OPENPADCHAT' , channel , function ( err , obj ) {
if ( err || ( obj && obj . error ) ) { console . error ( err || ( obj && obj . error ) ) ; }
} ) ;
} ;
2017-08-17 16:28:05 +00:00
2019-09-17 09:05:32 +00:00
// Team Chat
var teamChatChannel ;
funcs . setTeamChat = function ( channel ) {
teamChatChannel = channel ;
} ;
funcs . getTeamChat = function ( ) {
return teamChatChannel ;
} ;
2020-11-17 15:02:06 +00:00
// When opening a pad, if were an owner check the history size and prompt for trimming if
// necessary
funcs . checkTrimHistory = function ( channels , isDrive ) {
channels = channels || [ ] ;
var priv = ctx . metadataMgr . getPrivateData ( ) ;
var limit = 100 * 1024 * 1024 ; // 100MB
var owned ;
nThen ( function ( w ) {
if ( isDrive ) {
funcs . getAttribute ( [ 'drive' , 'trim' ] , w ( function ( err , val ) {
if ( err || typeof ( val ) !== "number" ) { return ; }
if ( val < ( + new Date ( ) ) ) { return ; }
w . abort ( ) ;
} ) ) ;
return ;
}
funcs . getPadAttribute ( 'trim' , w ( function ( err , val ) {
if ( err || typeof ( val ) !== "number" ) { return ; }
if ( val < ( + new Date ( ) ) ) { return ; }
w . abort ( ) ;
} ) ) ;
} ) . nThen ( function ( w ) {
// Check ownership
// DRIVE
if ( isDrive ) {
if ( ! priv . isDriveOwned ) { return void w . abort ( ) ; }
return ;
}
// PAD
channels . push ( { channel : priv . channel } ) ;
funcs . getPadMetadata ( {
channel : priv . channel
} , w ( function ( md ) {
if ( md && md . error ) { return void w . abort ( ) ; }
var owners = md . owners ;
owned = funcs . isOwned ( owners ) ;
if ( ! owned ) { return void w . abort ( ) ; }
} ) ) ;
} ) . nThen ( function ( ) {
// We're an owner: check the history size
var history = funcs . makeUniversal ( 'history' ) ;
history . execCommand ( 'GET_HISTORY_SIZE' , {
account : isDrive ,
pad : ! isDrive ,
channels : channels ,
teamId : typeof ( owned ) === "number" && owned
} , function ( obj ) {
if ( obj && obj . error ) { return ; } // can't get history size: abort
var bytes = obj . size ;
if ( ! bytes || typeof ( bytes ) !== "number" ) { return ; } // no history: abort
if ( bytes < limit ) { return ; }
obj . drive = isDrive ;
UIElements . displayTrimHistoryPrompt ( funcs , obj ) ;
} ) ;
} ) ;
} ;
2018-12-04 16:18:42 +00:00
var cursorChannel ;
2018-12-12 12:48:28 +00:00
// common-ui-elements needs to be able to get the cursor channel to put it in metadata when
// importing a template
2018-12-04 16:18:42 +00:00
funcs . getCursorChannel = function ( ) {
return cursorChannel ;
} ;
funcs . openCursorChannel = function ( saveChanges ) {
var md = JSON . parse ( JSON . stringify ( ctx . metadataMgr . getMetadata ( ) ) ) ;
2019-01-14 14:27:09 +00:00
var channel = md . cursor ;
if ( typeof ( channel ) !== 'string' || channel . length !== Hash . ephemeralChannelLength ) {
channel = Hash . createChannelId ( true ) ; // true indicates that it's an ephemeral channel
}
2019-01-29 10:40:44 +00:00
if ( md . cursor !== channel ) {
2018-12-04 16:18:42 +00:00
md . cursor = channel ;
ctx . metadataMgr . updateMetadata ( md ) ;
setTimeout ( saveChanges ) ;
}
cursorChannel = channel ;
ctx . sframeChan . query ( 'Q_CURSOR_OPENCHANNEL' , channel , function ( err , obj ) {
if ( err || ( obj && obj . error ) ) { console . error ( err || ( obj && obj . error ) ) ; }
} ) ;
} ;
2017-09-07 16:56:58 +00:00
// CodeMirror
funcs . initCodeMirrorApp = callWithCommon ( CodeMirror . create ) ;
2017-08-17 16:28:05 +00:00
2017-09-06 14:05:20 +00:00
// Window
2017-08-18 14:34:41 +00:00
funcs . logout = function ( cb ) {
2017-09-06 16:26:10 +00:00
cb = cb || $ . noop ;
ctx . sframeChan . query ( 'Q_LOGOUT' , null , cb ) ;
2017-08-18 14:34:41 +00:00
} ;
2018-10-02 10:08:25 +00:00
funcs . notify = function ( data ) {
ctx . sframeChan . event ( 'EV_NOTIFY' , data ) ;
2017-08-29 09:20:02 +00:00
} ;
2017-09-08 16:21:11 +00:00
funcs . setTabTitle = function ( newTitle ) {
ctx . sframeChan . event ( 'EV_SET_TAB_TITLE' , newTitle ) ;
} ;
2017-08-29 09:20:02 +00:00
2019-03-27 16:00:28 +00:00
funcs . setHash = function ( hash ) {
ctx . sframeChan . event ( 'EV_SET_HASH' , hash ) ;
} ;
2020-10-30 14:00:12 +00:00
funcs . setLoginRedirect = function ( page ) {
ctx . sframeChan . query ( 'EV_SET_LOGIN_REDIRECT' , page ) ;
2017-08-18 14:34:41 +00:00
} ;
2017-09-07 16:56:58 +00:00
funcs . isPresentUrl = function ( cb ) {
ctx . sframeChan . query ( 'Q_PRESENT_URL_GET_VALUE' , null , cb ) ;
} ;
funcs . setPresentUrl = function ( value ) {
ctx . sframeChan . event ( 'EV_PRESENT_URL_SET_VALUE' , value ) ;
} ;
2017-09-06 14:05:20 +00:00
// Store
2019-02-05 14:58:49 +00:00
funcs . handleNewFile = function ( waitFor , config ) {
2018-04-10 14:38:31 +00:00
if ( window . _ _CRYPTPAD _TEST _ _ ) { return ; }
2018-02-26 17:23:12 +00:00
var priv = ctx . metadataMgr . getPrivateData ( ) ;
if ( priv . isNewFile ) {
var c = ( priv . settings . general && priv . settings . general . creation ) || { } ;
// If this is a new file but we have a hash in the URL and pad creation screen is
// not displayed, then display an error...
2020-03-27 14:47:59 +00:00
if ( priv . isDeleted && ! funcs . isLoggedIn ( ) ) {
2018-02-26 17:23:12 +00:00
UI . errorLoadingScreen ( Messages . inactiveError , false , function ( ) {
UI . addLoadingScreen ( ) ;
return void funcs . createPad ( { } , waitFor ( ) ) ;
} ) ;
return ;
}
// Otherwise, if we don't display the screen, it means it is not a deleted pad
// so we can continue and start realtime...
2020-03-27 14:47:59 +00:00
if ( ! funcs . isLoggedIn ( ) ) {
2018-02-26 17:23:12 +00:00
return void funcs . createPad ( c , waitFor ( ) ) ;
}
// If we display the pad creation screen, it will handle deleted pads directly
2019-02-05 14:58:49 +00:00
funcs . getPadCreationScreen ( c , config , waitFor ( ) ) ;
2020-01-09 16:30:15 +00:00
return ;
}
if ( priv . burnAfterReading ) {
UIElements . displayBurnAfterReadingPage ( funcs , waitFor ( function ( ) {
2020-10-28 15:10:34 +00:00
UI . addLoadingScreen ( { newProgress : true } ) ;
if ( window . CryptPad _updateLoadingProgress ) {
window . CryptPad _updateLoadingProgress ( {
type : 'pad' ,
progress : 0
} ) ;
}
2020-01-09 16:30:15 +00:00
ctx . sframeChan . event ( 'EV_BURN_AFTER_READING' ) ;
} ) ) ;
2018-02-26 17:23:12 +00:00
}
} ;
2018-01-11 15:02:05 +00:00
funcs . createPad = function ( cfg , cb ) {
2021-06-14 11:59:53 +00:00
//var priv = ctx.metadataMgr.getPrivateData();
2021-05-18 08:47:11 +00:00
if ( AppConfig . disableAnonymousPadCreation && ! funcs . isLoggedIn ( ) ) {
return void UI . errorLoadingScreen ( Messages . mustLogin ) ;
}
2018-01-11 15:02:05 +00:00
ctx . sframeChan . query ( "Q_CREATE_PAD" , {
owned : cfg . owned ,
expire : cfg . expire ,
2018-04-25 17:03:58 +00:00
password : cfg . password ,
2019-09-12 15:54:50 +00:00
team : cfg . team ,
2018-03-13 10:31:08 +00:00
template : cfg . template ,
2021-06-15 09:45:54 +00:00
templateId : cfg . templateId ,
templateContent : cfg . templateContent
2018-01-11 15:02:05 +00:00
} , cb ) ;
} ;
2020-04-21 10:04:24 +00:00
funcs . isOwned = function ( owners ) {
var priv = ctx . metadataMgr . getPrivateData ( ) ;
var edPublic = priv . edPublic ;
var owned = false ;
if ( Array . isArray ( owners ) && owners . length ) {
if ( owners . indexOf ( edPublic ) !== - 1 ) {
owned = true ;
} else {
Object . keys ( priv . teams || { } ) . some ( function ( id ) {
var team = priv . teams [ id ] || { } ;
if ( team . viewer ) { return ; }
if ( owners . indexOf ( team . edPublic ) === - 1 ) { return ; }
owned = Number ( id ) ;
return true ;
} ) ;
}
}
return owned ;
} ;
2018-08-28 10:12:47 +00:00
funcs . isPadStored = function ( cb ) {
ctx . sframeChan . query ( "Q_IS_PAD_STORED" , null , function ( err , obj ) {
cb ( err || ( obj && obj . error ) , obj ) ;
} ) ;
} ;
2017-08-21 10:01:38 +00:00
funcs . sendAnonRpcMsg = function ( msg , content , cb ) {
ctx . sframeChan . query ( 'Q_ANON_RPC_MESSAGE' , {
msg : msg ,
content : content
} , function ( err , data ) {
if ( cb ) { cb ( data ) ; }
} ) ;
} ;
2019-09-23 13:45:24 +00:00
funcs . getPinUsage = function ( teamId , cb ) {
2017-09-21 15:56:24 +00:00
cb = cb || $ . noop ;
2019-09-23 13:45:24 +00:00
ctx . sframeChan . query ( 'Q_PIN_GET_USAGE' , teamId , function ( err , data ) {
2017-09-21 15:56:24 +00:00
cb ( err || data . error , data . data ) ;
} ) ;
} ;
2017-08-21 10:01:38 +00:00
2017-08-21 10:24:33 +00:00
funcs . isOverPinLimit = function ( cb ) {
ctx . sframeChan . query ( 'Q_GET_PIN_LIMIT_STATUS' , null , function ( err , data ) {
cb ( data . error , data . overLimit , data . limits ) ;
} ) ;
} ;
2018-05-15 16:18:56 +00:00
// href is optional here: if not provided, we use the href of the current tab
funcs . getPadAttribute = function ( key , cb , href ) {
2017-08-30 16:47:50 +00:00
ctx . sframeChan . query ( 'Q_GET_PAD_ATTRIBUTE' , {
2018-05-15 16:18:56 +00:00
key : key ,
href : href
2017-08-30 16:47:50 +00:00
} , function ( err , res ) {
2020-01-21 10:01:07 +00:00
cb ( err || res . error , res && res . data ) ;
2017-08-30 16:47:50 +00:00
} ) ;
} ;
2018-05-15 16:18:56 +00:00
funcs . setPadAttribute = function ( key , value , cb , href ) {
2017-10-12 15:43:49 +00:00
cb = cb || $ . noop ;
2017-08-30 16:47:50 +00:00
ctx . sframeChan . query ( 'Q_SET_PAD_ATTRIBUTE' , {
key : key ,
2018-05-15 16:18:56 +00:00
href : href ,
2017-08-30 16:47:50 +00:00
value : value
2017-08-31 14:32:26 +00:00
} , cb ) ;
} ;
2017-09-06 14:05:20 +00:00
funcs . getAttribute = function ( key , cb ) {
ctx . sframeChan . query ( 'Q_GET_ATTRIBUTE' , {
key : key
} , function ( err , res ) {
cb ( err || res . error , res . data ) ;
} ) ;
} ;
funcs . setAttribute = function ( key , value , cb ) {
cb = cb || $ . noop ;
ctx . sframeChan . query ( 'Q_SET_ATTRIBUTE' , {
key : key ,
value : value
} , cb ) ;
} ;
2017-11-07 13:51:53 +00:00
// Thumbnails
funcs . setThumbnail = function ( key , value , cb ) {
cb = cb || $ . noop ;
ctx . sframeChan . query ( 'Q_THUMBNAIL_SET' , {
key : key ,
value : value
} , cb ) ;
} ;
funcs . getThumbnail = function ( key , cb ) {
ctx . sframeChan . query ( 'Q_THUMBNAIL_GET' , {
key : key
} , function ( err , res ) {
cb ( err || res . error , res . data ) ;
} ) ;
} ;
2017-09-07 16:56:58 +00:00
funcs . setDisplayName = function ( name , cb ) {
cb = cb || $ . noop ;
ctx . sframeChan . query ( 'Q_SETTINGS_SET_DISPLAY_NAME' , name , cb ) ;
} ;
2017-09-22 17:35:06 +00:00
funcs . mergeAnonDrive = function ( cb ) {
ctx . sframeChan . query ( 'Q_MERGE_ANON_DRIVE' , null , cb ) ;
} ;
2019-05-21 16:43:11 +00:00
// Create friend request
2017-08-28 14:21:05 +00:00
funcs . getPendingFriends = function ( ) {
2019-05-21 16:43:11 +00:00
return ctx . metadataMgr . getPrivateData ( ) . pendingFriends ;
} ;
funcs . sendFriendRequest = function ( data , cb ) {
ctx . sframeChan . query ( 'Q_SEND_FRIEND_REQUEST' , data , cb ) ;
} ;
// Friend requests received
var friendRequests = { } ;
funcs . addFriendRequest = function ( data ) {
var curve = Util . find ( data , [ 'content' , 'msg' , 'author' ] ) ;
friendRequests [ curve ] = data ;
2017-08-28 14:21:05 +00:00
} ;
2019-05-22 16:03:52 +00:00
funcs . removeFriendRequest = function ( hash ) {
Object . keys ( friendRequests ) . some ( function ( curve ) {
var h = Util . find ( friendRequests [ curve ] , [ 'content' , 'hash' ] ) ;
if ( h === hash ) {
delete friendRequests [ curve ] ;
return true ;
}
} ) ;
} ;
2019-05-21 16:43:11 +00:00
funcs . getFriendRequests = function ( ) {
return JSON . parse ( JSON . stringify ( friendRequests ) ) ;
2017-08-28 14:21:05 +00:00
} ;
2019-08-28 13:29:38 +00:00
funcs . getFriends = function ( meIncluded ) {
2019-06-04 13:57:39 +00:00
var priv = ctx . metadataMgr . getPrivateData ( ) ;
var friends = priv . friends ;
var goodFriends = { } ;
Object . keys ( friends ) . forEach ( function ( curve ) {
2019-08-28 13:29:38 +00:00
if ( curve . length !== 44 && ! meIncluded ) { return ; }
2019-06-04 13:57:39 +00:00
var data = friends [ curve ] ;
if ( ! data . notifications ) { return ; }
goodFriends [ curve ] = friends [ curve ] ;
} ) ;
return goodFriends ;
} ;
2017-08-28 14:21:05 +00:00
// Feedback
2017-09-06 16:26:10 +00:00
funcs . prepareFeedback = function ( key ) {
2017-08-22 16:18:58 +00:00
if ( typeof ( key ) !== 'string' ) { return $ . noop ; }
2017-08-21 13:20:38 +00:00
2017-08-22 16:18:58 +00:00
var type = ctx . metadataMgr . getMetadata ( ) . type ;
return function ( ) {
2017-11-23 11:28:49 +00:00
Feedback . send ( ( key + ( type ? '_' + type : '' ) ) . toUpperCase ( ) ) ;
2017-08-22 16:18:58 +00:00
} ;
} ;
2017-08-21 13:20:38 +00:00
2017-09-06 16:26:10 +00:00
// RESTRICTED
// Filepicker app
2017-09-05 09:35:15 +00:00
funcs . getFilesList = function ( types , cb ) {
ctx . sframeChan . query ( 'Q_GET_FILES_LIST' , types , function ( err , data ) {
2017-08-31 14:32:26 +00:00
cb ( err || data . error , data . data ) ;
} ) ;
} ;
2020-11-30 11:07:03 +00:00
funcs . getCache = function ( ) {
return ctx . cache ;
} ;
2017-08-18 16:43:04 +00:00
/ * f u n c s . s t o r e L i n k T o C l i p b o a r d = f u n c t i o n ( r e a d O n l y , c b ) {
2017-08-18 14:34:41 +00:00
ctx . sframeChan . query ( 'Q_STORE_LINK_TO_CLIPBOARD' , readOnly , function ( err ) {
if ( cb ) { cb ( err ) ; }
} ) ;
2017-09-06 16:26:10 +00:00
} ; * /
2017-08-30 15:57:10 +00:00
2019-08-14 12:49:40 +00:00
funcs . getPad = function ( data , cb ) {
ctx . sframeChan . query ( "Q_CRYPTGET" , data , function ( err , obj ) {
if ( err ) { return void cb ( err ) ; }
if ( obj . error ) { return void cb ( obj . error ) ; }
cb ( null , obj . data ) ;
} , { timeout : 60000 } ) ;
} ;
2019-08-30 15:36:27 +00:00
funcs . getPadMetadata = function ( data , cb ) {
ctx . sframeChan . query ( 'Q_GET_PAD_METADATA' , data , function ( err , val ) {
if ( err || ( val && val . error ) ) { return void cb ( { error : err || val . error } ) ; }
cb ( val ) ;
} ) ;
} ;
2017-09-11 13:46:21 +00:00
funcs . gotoURL = function ( url ) { ctx . sframeChan . event ( 'EV_GOTO_URL' , url ) ; } ;
2017-09-22 17:35:06 +00:00
funcs . openURL = function ( url ) { ctx . sframeChan . event ( 'EV_OPEN_URL' , url ) ; } ;
2020-11-05 16:38:24 +00:00
funcs . getBounceURL = function ( url ) {
return window . location . origin + '/bounce/#' + encodeURIComponent ( url ) ;
} ;
2017-11-27 13:44:44 +00:00
funcs . openUnsafeURL = function ( url ) {
2020-12-01 14:01:04 +00:00
var app = ctx . metadataMgr . getPrivateData ( ) . app ;
if ( app === "sheet" ) {
return void ctx . sframeChan . event ( 'EV_OPEN_UNSAFE_URL' , url ) ;
}
2017-11-27 13:44:44 +00:00
var bounceHref = window . location . origin + '/bounce/#' + encodeURIComponent ( url ) ;
window . open ( bounceHref ) ;
} ;
2017-09-11 13:46:21 +00:00
2018-03-23 14:05:26 +00:00
funcs . fixLinks = function ( domElement ) {
var origin = ctx . metadataMgr . getPrivateData ( ) . origin ;
$ ( domElement ) . find ( 'a[target="_blank"]' ) . click ( function ( e ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
var href = $ ( this ) . attr ( 'href' ) ;
var absolute = /^https?:\/\//i ;
if ( ! absolute . test ( href ) ) {
if ( href . slice ( 0 , 1 ) !== '/' ) { href = '/' + href ; }
href = origin + href ;
}
funcs . openUnsafeURL ( href ) ;
} ) ;
$ ( domElement ) . find ( 'a[target!="_blank"]' ) . click ( function ( e ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
funcs . gotoURL ( $ ( this ) . attr ( 'href' ) ) ;
} ) ;
return $ ( domElement ) [ 0 ] ;
} ;
2017-09-11 13:46:21 +00:00
funcs . whenRealtimeSyncs = evRealtimeSynced . reg ;
2017-11-13 16:28:09 +00:00
var logoutHandlers = [ ] ;
funcs . onLogout = function ( h ) {
if ( typeof ( h ) !== "function" ) { return ; }
if ( logoutHandlers . indexOf ( h ) !== - 1 ) { return ; }
logoutHandlers . push ( h ) ;
} ;
2018-11-05 15:53:25 +00:00
var shortcuts = [ ] ;
2019-08-23 10:16:48 +00:00
funcs . addShortcuts = function ( w , isApp ) {
2018-11-05 15:53:25 +00:00
w = w || window ;
if ( shortcuts . indexOf ( w ) !== - 1 ) { return ; }
shortcuts . push ( w ) ;
$ ( w ) . keydown ( function ( e ) {
// Ctrl || Meta (mac)
if ( e . ctrlKey || ( navigator . platform === "MacIntel" && e . metaKey ) ) {
// Ctrl+E: New pad modal
2019-08-23 10:16:48 +00:00
if ( e . which === 69 && isApp ) {
2018-11-05 15:53:25 +00:00
e . preventDefault ( ) ;
return void funcs . createNewPadModal ( ) ;
}
// Ctrl+S: prevent default (save)
if ( e . which === 83 ) { return void e . preventDefault ( ) ; }
}
} ) ;
} ;
2017-11-13 16:28:09 +00:00
2021-03-11 11:27:12 +00:00
funcs . isAdmin = function ( ) {
var privateData = ctx . metadataMgr . getPrivateData ( ) ;
return privateData . edPublic && Array . isArray ( ApiConfig . adminKeys ) &&
ApiConfig . adminKeys . indexOf ( privateData . edPublic ) !== - 1 ;
} ;
2019-05-17 14:19:41 +00:00
funcs . mailbox = { } ;
2017-08-17 14:56:18 +00:00
Object . freeze ( funcs ) ;
return { create : function ( cb ) {
2017-09-27 14:53:16 +00:00
if ( window . CryptPad _sframe _common ) {
2018-01-16 10:26:16 +00:00
throw new Error ( "Sframe-common should only be created once" ) ;
2017-09-27 14:53:16 +00:00
}
2018-01-16 10:26:16 +00:00
window . CryptPad _sframe _common = true ;
2017-09-27 14:53:16 +00:00
2020-10-15 12:48:17 +00:00
if ( window . CryptPad _updateLoadingProgress ) {
window . CryptPad _updateLoadingProgress ( {
type : 'drive' ,
progress : 0
} ) ;
}
2017-08-17 14:56:18 +00:00
nThen ( function ( waitFor ) {
2019-01-11 14:22:52 +00:00
var msgEv = Util . mkEvent ( ) ;
var iframe = window . parent ;
window . addEventListener ( 'message' , function ( msg ) {
if ( msg . source !== iframe ) { return ; }
msgEv . fire ( msg ) ;
} ) ;
var postMsg = function ( data ) {
iframe . postMessage ( data , '*' ) ;
} ;
SFrameChannel . create ( msgEv , postMsg , waitFor ( function ( sfc ) { ctx . sframeChan = sfc ; } ) ) ;
2017-11-30 16:21:58 +00:00
} ) . nThen ( function ( waitFor ) {
2017-11-07 13:51:53 +00:00
localForage . clear ( ) ;
2017-12-07 11:20:26 +00:00
Language . applyTranslation ( ) ;
2017-11-07 13:51:53 +00:00
2017-08-17 17:58:48 +00:00
ctx . metadataMgr = MetadataMgr . create ( ctx . sframeChan ) ;
2017-08-25 12:24:43 +00:00
2017-09-14 08:23:05 +00:00
ctx . sframeChan . whenReg ( 'EV_CACHE_PUT' , function ( ) {
if ( Object . keys ( window . cryptpadCache . updated ) . length ) {
ctx . sframeChan . event ( 'EV_CACHE_PUT' , window . cryptpadCache . updated ) ;
}
window . cryptpadCache . _put = window . cryptpadCache . put ;
window . cryptpadCache . put = function ( k , v , cb ) {
window . cryptpadCache . _put ( k , v , cb ) ;
var x = { } ;
x [ k ] = v ;
ctx . sframeChan . event ( 'EV_CACHE_PUT' , x ) ;
} ;
} ) ;
2017-09-21 15:56:24 +00:00
ctx . sframeChan . whenReg ( 'EV_LOCALSTORE_PUT' , function ( ) {
if ( Object . keys ( window . cryptpadStore . updated ) . length ) {
ctx . sframeChan . event ( 'EV_LOCALSTORE_PUT' , window . cryptpadStore . updated ) ;
}
window . cryptpadStore . _put = window . cryptpadStore . put ;
window . cryptpadStore . put = function ( k , v , cb ) {
window . cryptpadStore . _put ( k , v , cb ) ;
var x = { } ;
x [ k ] = v ;
2021-01-18 17:05:01 +00:00
ctx . sframeChan . event ( 'EV_LOCALSTORE_PUT' , x , { raw : true } ) ;
2017-09-21 15:56:24 +00:00
} ;
} ) ;
2017-09-14 08:23:05 +00:00
2017-11-13 11:00:15 +00:00
UI . addTooltips ( ) ;
2017-09-12 12:12:35 +00:00
2020-01-29 17:40:18 +00:00
ctx . sframeChan . on ( "EV_PAD_NODATA" , function ( ) {
2021-03-24 09:11:47 +00:00
var error = Pages . setHTML ( h ( 'span' ) , Messages . safeLinks _error ) ;
var i = error . querySelector ( 'i' ) ;
if ( i ) { i . classList = 'fa fa-shhare-alt' ; }
var a = error . querySelector ( 'a' ) ;
if ( a ) {
2021-04-12 09:24:52 +00:00
a . setAttribute ( 'href' , Pages . localizeDocsLink ( "https://docs.cryptpad.fr/en/user_guide/user_account.html#confidentiality" ) ) ;
2021-03-24 09:11:47 +00:00
}
UI . errorLoadingScreen ( error ) ;
2020-01-28 10:37:28 +00:00
} ) ;
2019-11-19 09:40:55 +00:00
ctx . sframeChan . on ( "EV_PAD_PASSWORD" , function ( cfg ) {
UIElements . displayPasswordPrompt ( funcs , cfg ) ;
2018-04-25 17:03:58 +00:00
} ) ;
2020-06-24 09:20:43 +00:00
ctx . sframeChan . on ( "EV_RESTRICTED_ERROR" , function ( ) {
UI . errorLoadingScreen ( Messages . restrictedError ) ;
} ) ;
2019-10-21 15:12:36 +00:00
ctx . sframeChan . on ( "EV_PAD_PASSWORD_ERROR" , function ( ) {
UI . errorLoadingScreen ( Messages . password _error _seed ) ;
} ) ;
2020-12-01 14:01:04 +00:00
ctx . sframeChan . on ( "EV_POPUP_BLOCKED" , function ( ) {
UI . alert ( Messages . errorPopupBlocked ) ;
} ) ;
2020-06-24 13:37:21 +00:00
ctx . sframeChan . on ( "EV_EXPIRED_ERROR" , function ( ) {
funcs . onServerError ( {
type : 'EEXPIRED'
} ) ;
} ) ;
2018-05-04 16:41:54 +00:00
ctx . sframeChan . on ( 'EV_LOADING_INFO' , function ( data ) {
2020-10-14 13:20:56 +00:00
//UI.updateLoadingProgress(data, 'drive');
UI . updateLoadingProgress ( data ) ;
2018-05-04 16:41:54 +00:00
} ) ;
2018-06-11 14:52:26 +00:00
ctx . sframeChan . on ( 'EV_NEW_VERSION' , function ( ) {
2020-10-07 11:19:48 +00:00
// TODO lock the UI and do the same in non-framework apps
2018-06-11 16:18:39 +00:00
var $err = $ ( '<div>' ) . append ( Messages . newVersionError ) ;
$err . find ( 'a' ) . click ( function ( ) {
funcs . gotoURL ( ) ;
} ) ;
2021-03-23 13:06:52 +00:00
UI . findOKButton ( ) . click ( ) ; // FIXME this might be randomly clicking something dangerous...
2018-06-11 16:18:39 +00:00
UI . errorLoadingScreen ( $err , true , true ) ;
2018-06-11 14:52:26 +00:00
} ) ;
2018-08-28 09:42:48 +00:00
ctx . sframeChan . on ( 'EV_AUTOSTORE_DISPLAY_POPUP' , function ( data ) {
UIElements . displayStorePadPopup ( funcs , data ) ;
2018-08-27 12:58:09 +00:00
} ) ;
2019-02-06 14:35:27 +00:00
ctx . sframeChan . on ( 'EV_LOADING_ERROR' , function ( err ) {
var msg = err ;
if ( err === 'DELETED' ) {
msg = Messages . deletedError + '<br>' + Messages . errorRedirectToHome ;
}
if ( err === "INVALID_HASH" ) {
2019-02-12 10:19:59 +00:00
msg = Messages . invalidHashError ;
2019-02-06 14:35:27 +00:00
}
UI . errorLoadingScreen ( msg , false , function ( ) {
funcs . gotoURL ( '/drive/' ) ;
} ) ;
} ) ;
2019-05-24 15:45:03 +00:00
ctx . sframeChan . on ( 'EV_UNIVERSAL_EVENT' , function ( obj ) {
var type = obj . type ;
if ( ! type || ! modules [ type ] ) { return ; }
2021-03-30 13:18:58 +00:00
modules [ type ] . fire ( obj . data ) ;
2019-05-24 15:45:03 +00:00
} ) ;
2020-11-30 11:07:03 +00:00
ctx . cache = Cache . create ( ctx . sframeChan ) ;
2017-11-30 16:21:58 +00:00
ctx . metadataMgr . onReady ( waitFor ( ) ) ;
2018-11-05 15:53:25 +00:00
2017-11-30 16:21:58 +00:00
} ) . nThen ( function ( ) {
2019-08-23 10:16:48 +00:00
var privateData = ctx . metadataMgr . getPrivateData ( ) ;
funcs . addShortcuts ( window , Boolean ( privateData . app ) ) ;
2020-11-26 17:15:36 +00:00
var mt = Util . find ( privateData , [ 'settings' , 'general' , 'mediatag-size' ] ) ;
if ( MT . MediaTag && typeof ( mt ) === "number" ) {
var maxMtSize = mt === - 1 ? Infinity : mt * 1024 * 1024 ;
MT . MediaTag . setDefaultConfig ( 'maxDownloadSize' , maxMtSize ) ;
}
2020-11-30 11:07:03 +00:00
if ( MT . MediaTag && ctx . cache ) {
MT . MediaTag . setDefaultConfig ( 'Cache' , ctx . cache ) ;
2020-11-27 16:11:12 +00:00
}
2018-01-29 11:45:38 +00:00
try {
2019-08-23 10:16:48 +00:00
var feedback = privateData . feedbackAllowed ;
2018-01-29 11:45:38 +00:00
Feedback . init ( feedback ) ;
} catch ( e ) { Feedback . init ( false ) ; }
2018-03-21 17:27:20 +00:00
2021-01-19 15:58:56 +00:00
if ( privateData . secureIframe ) {
UI . log = function ( msg ) { ctx . sframeChan . event ( 'EV_ALERTIFY_LOG' , msg ) ; } ;
UI . warn = function ( msg ) { ctx . sframeChan . event ( 'EV_ALERTIFY_WARN' , msg ) ; } ;
} else {
ctx . sframeChan . on ( 'EV_ALERTIFY_LOG' , function ( msg ) { UI . log ( msg ) ; } ) ;
ctx . sframeChan . on ( 'EV_ALERTIFY_WARN' , function ( msg ) { UI . warn ( msg ) ; } ) ;
}
2018-12-12 13:52:58 +00:00
try {
2019-08-23 10:16:48 +00:00
var forbidden = privateData . disabledApp ;
2018-12-12 13:52:58 +00:00
if ( forbidden ) {
UI . alert ( Messages . disabledApp , function ( ) {
funcs . gotoURL ( '/drive/' ) ;
} , { forefront : true } ) ;
return ;
}
2019-08-23 10:16:48 +00:00
var mustLogin = privateData . registeredOnly ;
2018-12-12 13:52:58 +00:00
if ( mustLogin ) {
UI . alert ( Messages . mustLogin , function ( ) {
2020-10-30 14:00:12 +00:00
funcs . setLoginRedirect ( 'login' ) ;
2018-12-12 13:52:58 +00:00
} , { forefront : true } ) ;
return ;
}
} catch ( e ) {
console . error ( "Can't check permissions for the app" ) ;
}
2019-01-31 14:27:01 +00:00
try {
2019-08-23 10:16:48 +00:00
window . CP _DEV _MODE = privateData . devMode ;
2019-01-31 14:27:01 +00:00
} catch ( e ) { }
2018-03-21 17:27:20 +00:00
ctx . sframeChan . on ( 'EV_LOGOUT' , function ( ) {
$ ( window ) . on ( 'keyup' , function ( e ) {
if ( e . keyCode === 27 ) {
UI . removeLoadingScreen ( ) ;
}
} ) ;
UI . addLoadingScreen ( { hideTips : true } ) ;
2019-08-23 10:16:48 +00:00
var origin = privateData . origin ;
2018-03-21 17:27:20 +00:00
var href = origin + "/login/" ;
var onLogoutMsg = Messages . _getKey ( 'onLogout' , [ '<a href="' + href + '" target="_blank">' , '</a>' ] ) ;
UI . errorLoadingScreen ( onLogoutMsg , true ) ;
logoutHandlers . forEach ( function ( h ) {
if ( typeof ( h ) === "function" ) { h ( ) ; }
} ) ;
} ) ;
2019-04-15 12:21:04 +00:00
ctx . sframeChan . on ( 'EV_WORKER_TIMEOUT' , function ( ) {
2021-08-16 13:08:33 +00:00
UI . errorLoadingScreen ( Messages . timeoutError , false , function ( ) { // XXX 4.11.0 mobile users can't necessarily hit 'ESC' as this message suggests. provice a click option
2019-05-02 08:49:42 +00:00
funcs . gotoURL ( '' ) ;
} ) ;
2019-04-15 12:21:04 +00:00
} ) ;
2018-08-28 15:44:15 +00:00
ctx . sframeChan . on ( 'EV_CHROME_68' , function ( ) {
UI . alert ( Messages . chrome68 ) ;
} ) ;
2018-09-13 16:47:46 +00:00
funcs . isPadStored ( function ( err , val ) {
if ( err || ! val ) { return ; }
UIElements . displayCrowdfunding ( funcs ) ;
} ) ;
2017-09-08 13:53:53 +00:00
ctx . sframeChan . ready ( ) ;
2019-05-15 16:22:39 +00:00
Mailbox . create ( funcs ) ;
2019-09-06 16:47:18 +00:00
cb ( funcs ) ;
2017-08-17 14:56:18 +00:00
} ) ;
} } ;
2017-08-17 14:28:54 +00:00
} ) ;