2024-06-11 00:48:44 +00:00
# include msgbox . jsx
2024-01-30 23:47:02 +00:00
# include utility . js
2024-12-17 21:23:38 +00:00
# include xhr . js
2024-01-30 23:47:02 +00:00
# include messages / actbtn . js
# include messages / list . js
# include messages / recipient . js
# include messages / reply . jsx
# include messages / thread . js
const MszMessages = ( ) => {
const extractMsgIds = msg => {
if ( typeof msg . getId === 'function' )
2024-11-30 04:20:20 +00:00
return msg . id ;
2024-01-30 23:47:02 +00:00
if ( typeof msg . toString === 'function' )
return msg . toString ( ) ;
throw 'unsupported message type' ;
} ;
const displayErrorMessage = async error => {
let text ;
if ( typeof error === 'string' )
text = error ;
else if ( typeof error . text === 'string' )
text = error . text ;
else if ( typeof error . toString === 'function' )
text = error . toString ( ) ;
else
text = 'Something indescribable happened.' ;
await MszShowMessageBox ( text , 'Error' ) ;
return false ;
} ;
const msgsCreate = async ( title , text , parser , draft , recipient , replyTo ) => {
const formData = new FormData ;
formData . append ( 'title' , title ) ;
formData . append ( 'body' , text ) ;
formData . append ( 'parser' , parser ) ;
formData . append ( 'draft' , draft ) ;
formData . append ( 'recipient' , recipient ) ;
formData . append ( 'reply' , replyTo ) ;
2024-12-17 21:37:28 +00:00
const { body } = await $x . post ( '/messages/create' , { type : 'json' , csrf : true } , formData ) ;
2024-01-30 23:47:02 +00:00
if ( body . error !== undefined )
throw body . error ;
return body ;
} ;
const msgsUpdate = async ( messageId , title , text , parser , draft ) => {
const formData = new FormData ;
formData . append ( 'title' , title ) ;
formData . append ( 'body' , text ) ;
formData . append ( 'parser' , parser ) ;
formData . append ( 'draft' , draft ) ;
2024-12-17 21:37:28 +00:00
const { body } = await $x . post ( ` /messages/ ${ encodeURIComponent ( messageId ) } ` , { type : 'json' , csrf : true } , formData ) ;
2024-01-30 23:47:02 +00:00
if ( body . error !== undefined )
throw body . error ;
return body ;
} ;
const msgsMark = async ( msgs , state ) => {
2024-12-17 21:37:28 +00:00
const { body } = await $x . post ( '/messages/mark' , { type : 'json' , csrf : true } , {
2024-01-30 23:47:02 +00:00
type : state ,
messages : msgs . map ( extractMsgIds ) . join ( ',' ) ,
} ) ;
if ( body . error !== undefined )
throw body . error ;
return true ;
} ;
const msgsDelete = async msgs => {
2024-12-17 21:37:28 +00:00
const { body } = await $x . post ( '/messages/delete' , { type : 'json' , csrf : true } , {
2024-01-30 23:47:02 +00:00
messages : msgs . map ( extractMsgIds ) . join ( ',' ) ,
} ) ;
if ( body . error !== undefined )
throw body . error ;
return true ;
} ;
const msgsRestore = async msgs => {
2024-12-17 21:37:28 +00:00
const { body } = await $x . post ( '/messages/restore' , { type : 'json' , csrf : true } , {
2024-01-30 23:47:02 +00:00
messages : msgs . map ( extractMsgIds ) . join ( ',' ) ,
} ) ;
if ( body . error !== undefined )
throw body . error ;
return true ;
} ;
const msgsNuke = async msgs => {
2024-12-17 21:37:28 +00:00
const { body } = await $x . post ( '/messages/nuke' , { type : 'json' , csrf : true } , {
2024-01-30 23:47:02 +00:00
messages : msgs . map ( extractMsgIds ) . join ( ',' ) ,
} ) ;
if ( body . error !== undefined )
throw body . error ;
return true ;
} ;
const msgsUserBtns = Array . from ( $qa ( '.js-header-pms-button' ) ) ;
if ( msgsUserBtns . length > 0 )
$x . get ( '/messages/stats' , { type : 'json' } ) . then ( result => {
2024-12-17 21:37:28 +00:00
const body = result . body ;
2024-01-30 23:47:02 +00:00
if ( typeof body === 'object' && typeof body . unread === 'number' )
if ( body . unread > 0 )
for ( const msgsUserBtn of msgsUserBtns )
msgsUserBtn . append ( $e ( { child : body . unread . toLocaleString ( ) , attrs : { className : 'header__desktop__user__button__count' } } ) ) ;
} ) ;
const msgsListElem = $q ( '.js-messages-list' ) ;
const msgsList = msgsListElem instanceof Element ? new MsgMessagesList ( msgsListElem ) : undefined ;
const msgsListEmptyNotice = $q ( '.js-messages-folder-empty' ) ;
const msgsThreadElem = $q ( '.js-messages-thread' ) ;
const msgsThread = msgsThreadElem instanceof Element ? new MszMessagesThread ( msgsThreadElem ) : undefined ;
const msgsRecipientElem = $q ( '.js-messages-recipient' ) ;
const msgsRecipient = msgsRecipientElem instanceof Element ? new MszMessagesRecipient ( msgsRecipientElem ) : undefined ;
const msgsReplyElem = $q ( '.js-messages-reply' ) ;
const msgsReply = msgsReplyElem instanceof Element ? new MszMessagesReply ( msgsReplyElem ) : undefined ;
if ( msgsReply !== undefined ) {
if ( msgsRecipient !== undefined )
msgsRecipient . onUpdate ( async info => {
msgsReply . setRecipient ( typeof info . id === 'string' ? info . id : '' ) ;
2024-02-02 02:16:37 +00:00
msgsReply . setWarning ( info . ban ? ` ${ ( typeof info . name === 'string' ? info . name : 'This user' ) } has been banned and will be unable to respond to your messages. ` : undefined ) ;
2024-01-30 23:47:02 +00:00
} ) ;
msgsReply . onSubmit ( async form => {
try {
let result ;
if ( typeof form . message === 'string' ) {
result = await msgsUpdate (
form . message ,
form . title ,
form . body ,
form . parser ,
form . draft
) ;
} else {
result = await msgsCreate (
form . title ,
form . body ,
form . parser ,
form . draft ,
form . recipient ,
form . reply || ''
) ;
}
if ( typeof result . url === 'string' )
location . assign ( result . url ) ;
} catch ( ex ) {
return await displayErrorMessage ( ex ) ;
}
} ) ;
}
let actSelectAll , actMarkRead , actMoveTrash , actNuke ;
const actSelectAllBtn = $q ( '.js-messages-actions-select-all' ) ;
if ( actSelectAllBtn instanceof Element ) {
actSelectAll = new MszMessagesActionButton ( actSelectAllBtn ) ;
if ( msgsList !== undefined ) {
actSelectAll . setAction ( async state => {
msgsList . setAllSelected ( ! state ) ;
return ! state ;
} ) ;
msgsList . onSelectedChange ( ( selectedNo , itemNo ) => {
actSelectAll . setState ( selectedNo >= itemNo ) ;
} ) ;
actSelectAll . setState ( msgsList . getAllSelected ( ) ) ;
}
}
const actMarkReadBtn = $q ( '.js-messages-actions-mark-read' ) ;
if ( actMarkReadBtn instanceof Element ) {
actMarkRead = new MszMessagesActionButton ( actMarkReadBtn ) ;
if ( msgsList !== undefined ) {
msgsList . onSelectedChange ( selectedNo => {
const enabled = selectedNo > 0 ;
actMarkRead . setEnabled ( enabled ) ;
if ( enabled ) {
const items = msgsList . getSelectedItems ( ) ;
let readNo = 0 , unreadNo = 0 ;
for ( const item of items ) {
if ( item . isRead ( ) )
++ readNo ;
else
++ unreadNo ;
}
actMarkRead . setState ( readNo > unreadNo ) ;
}
} ) ;
actMarkRead . setAction ( async state => {
const items = msgsList . getSelectedItems ( ) ;
const result = await actMarkRead . disableWith ( async ( ) => {
try {
return await msgsMark ( items , state ? 'unread' : 'read' ) ;
} catch ( ex ) {
return await displayErrorMessage ( ex ) ;
}
} ) ;
if ( result ) {
state = ! state ;
for ( const item of items )
item . setRead ( state ) ;
return state ;
}
} ) ;
} else if ( msgsThread !== undefined ) {
actMarkRead . setAction ( async state => {
const items = [ msgsThread . getMessage ( ) ] ;
const result = await actMarkRead . disableWith ( async ( ) => {
try {
return await msgsMark ( items , state ? 'unread' : 'read' ) ;
} catch ( ex ) {
return await displayErrorMessage ( ex ) ;
}
} ) ;
return result ? ! state : state ;
} ) ;
}
}
const actMoveTrashBtn = $q ( '.js-messages-actions-move-trash' ) ;
if ( actMoveTrashBtn instanceof Element ) {
actMoveTrash = new MszMessagesActionButton ( actMoveTrashBtn ) ;
if ( msgsList !== undefined ) {
msgsList . onSelectedChange ( selectedNo => actMoveTrash . setEnabled ( selectedNo > 0 ) ) ;
actMoveTrash . setAction ( async state => {
const items = msgsList . getSelectedItems ( ) ;
if ( ! state && ! await MszShowConfirmBox ( ` Are you sure you wish to delete ${ items . length } item ${ items . length === 1 ? '' : 's' } ? ` , 'Confirmation' ) )
return ;
const result = await actMoveTrash . disableWith ( async ( ) => {
try {
if ( state )
return await msgsRestore ( items ) ;
return await msgsDelete ( items ) ;
} catch ( ex ) {
return await displayErrorMessage ( ex ) ;
}
} ) ;
if ( result )
for ( const message of items )
msgsList . removeItem ( message ) ;
if ( msgsListEmptyNotice instanceof Element )
msgsListEmptyNotice . hidden = msgsList . getItemsCount ( ) > 0 ;
} ) ;
} else if ( msgsThread !== undefined ) {
actMoveTrash . setAction ( async state => {
if ( ! state && ! await MszShowConfirmBox ( 'Are you sure you wish to delete this message?' , 'Confirmation' ) )
return ;
const items = [ msgsThread . getMessage ( ) ] ;
const result = await actMoveTrash . disableWith ( async ( ) => {
try {
if ( state )
return await msgsRestore ( items ) ;
return await msgsDelete ( items ) ;
} catch ( ex ) {
return await displayErrorMessage ( ex ) ;
}
} ) ;
if ( result ) {
state = ! state ;
if ( msgsReply !== undefined )
msgsReply . setHidden ( state ) ;
const msg = msgsThread . getMessage ( ) ;
if ( msg !== undefined )
msg . setDeleted ( state ) ;
return state ;
}
} ) ;
}
}
const actNukeBtn = $q ( '.js-messages-actions-nuke' ) ;
if ( actNukeBtn instanceof Element ) {
actNuke = new MszMessagesActionButton ( actNukeBtn , true ) ;
if ( msgsList !== undefined ) {
msgsList . onSelectedChange ( selectedNo => actNuke . setEnabled ( selectedNo > 0 ) ) ;
actNuke . setAction ( async ( ) => {
const items = msgsList . getSelectedItems ( ) ;
if ( ! await MszShowConfirmBox ( ` Are you sure you wish to PERMANENTLY delete ${ items . length } item ${ items . length === 1 ? '' : 's' } ? ` , 'Confirmation' ) )
return ;
const result = await actNuke . disableWith ( async ( ) => {
try {
return await msgsNuke ( items ) ;
} catch ( ex ) {
return await displayErrorMessage ( ex ) ;
}
} ) ;
if ( result )
for ( const message of items )
msgsList . removeItem ( message ) ;
if ( msgsListEmptyNotice instanceof Element )
msgsListEmptyNotice . hidden = msgsList . getItemsCount ( ) > 0 ;
} ) ;
} else if ( msgsThread !== undefined ) {
actMoveTrash . watchState ( state => {
actNuke . setHidden ( ! state ) ;
} ) ;
actNuke . setAction ( async ( ) => {
if ( ! await MszShowConfirmBox ( 'Are you sure you wish to PERMANENTLY delete this message?' , 'Confirmation' ) )
return ;
const items = [ msgsThread . getMessage ( ) ] ;
const result = await actNuke . disableWith ( async ( ) => {
try {
return await msgsNuke ( items ) ;
} catch ( ex ) {
return await displayErrorMessage ( ex ) ;
}
} ) ;
if ( result )
location . assign ( '/messages' ) ;
} ) ;
}
}
} ;