Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
converse.js
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
converse.js
Commits
e8536ebc
Commit
e8536ebc
authored
Dec 06, 2020
by
JC Brand
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move converse-muc-views plugin into own folder
parent
2b6c56f1
Changes
7
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
613 additions
and
570 deletions
+613
-570
src/converse.js
src/converse.js
+1
-1
src/plugins/muc-views/api.js
src/plugins/muc-views/api.js
+69
-0
src/plugins/muc-views/config-form.js
src/plugins/muc-views/config-form.js
+65
-0
src/plugins/muc-views/index.js
src/plugins/muc-views/index.js
+163
-0
src/plugins/muc-views/muc.js
src/plugins/muc-views/muc.js
+206
-569
src/plugins/muc-views/password-form.js
src/plugins/muc-views/password-form.js
+30
-0
src/plugins/muc-views/rooms-panel.js
src/plugins/muc-views/rooms-panel.js
+79
-0
No files found.
src/converse.js
View file @
e8536ebc
...
...
@@ -22,7 +22,7 @@ import "./plugins/dragresize.js"; // Allows chat boxes to be resized b
import
"
./plugins/fullscreen.js
"
;
import
"
./plugins/mam-views.js
"
;
import
"
./plugins/minimize.js
"
;
// Allows chat boxes to be minimized
import
"
./plugins/muc-views.js
"
;
// Views related to MUC
import
"
./plugins/muc-views
/index
.js
"
;
// Views related to MUC
import
"
./plugins/headlines-view.js
"
;
import
"
./plugins/notifications.js
"
;
import
"
./plugins/omemo.js
"
;
...
...
src/plugins/muc-views/api.js
0 → 100644
View file @
e8536ebc
import
{
_converse
,
api
}
from
"
@converse/headless/core
"
;
export
default
{
/**
* The "roomviews" namespace groups methods relevant to chatroom
* (aka groupchats) views.
*
* @namespace _converse.api.roomviews
* @memberOf _converse.api
*/
roomviews
:
{
/**
* Retrieves a groupchat (aka chatroom) view. The chat should already be open.
*
* @method _converse.api.roomviews.get
* @param {String|string[]} name - e.g. 'coven@conference.shakespeare.lit' or
* ['coven@conference.shakespeare.lit', 'cave@conference.shakespeare.lit']
* @returns {View} View representing the groupchat
*
* @example
* // To return a single view, provide the JID of the groupchat
* const view = _converse.api.roomviews.get('coven@conference.shakespeare.lit');
*
* @example
* // To return an array of views, provide an array of JIDs:
* const views = _converse.api.roomviews.get(['coven@conference.shakespeare.lit', 'cave@conference.shakespeare.lit']);
*
* @example
* // To return views of all open groupchats, call the method without any parameters::
* const views = _converse.api.roomviews.get();
*
*/
get
(
jids
)
{
if
(
Array
.
isArray
(
jids
))
{
const
views
=
api
.
chatviews
.
get
(
jids
);
return
views
.
filter
(
v
=>
v
.
model
.
get
(
'
type
'
)
===
_converse
.
CHATROOMS_TYPE
)
}
else
{
const
view
=
api
.
chatviews
.
get
(
jids
);
if
(
view
.
model
.
get
(
'
type
'
)
===
_converse
.
CHATROOMS_TYPE
)
{
return
view
;
}
else
{
return
null
;
}
}
},
/**
* Lets you close open chatrooms.
*
* You can call this method without any arguments to close
* all open chatrooms, or you can specify a single JID or
* an array of JIDs.
*
* @method _converse.api.roomviews.close
* @param {(String[]|String)} jids The JID or array of JIDs of the chatroom(s)
* @returns { Promise } - Promise which resolves once the views have been closed.
*/
close
(
jids
)
{
let
views
;
if
(
jids
===
undefined
)
{
views
=
_converse
.
chatboxviews
;
}
else
if
(
typeof
jids
===
'
string
'
)
{
views
=
[
_converse
.
chatboxviews
.
get
(
jids
)].
filter
(
v
=>
v
);
}
else
if
(
Array
.
isArray
(
jids
))
{
views
=
jids
.
map
(
jid
=>
_converse
.
chatboxviews
.
get
(
jid
));
}
return
Promise
.
all
(
views
.
map
(
v
=>
(
v
.
is_chatroom
&&
v
.
model
&&
v
.
close
())))
}
}
}
src/plugins/muc-views/config-form.js
0 → 100644
View file @
e8536ebc
import
log
from
"
@converse/headless/log
"
;
import
tpl_muc_config_form
from
"
templates/muc_config_form.js
"
;
import
{
View
}
from
'
@converse/skeletor/src/view.js
'
;
import
{
__
}
from
'
i18n
'
;
import
{
api
,
converse
}
from
"
@converse/headless/core
"
;
const
{
sizzle
}
=
converse
.
env
;
const
u
=
converse
.
env
.
utils
;
const
MUCConfigForm
=
View
.
extend
({
className
:
'
chatroom-form-container muc-config-form
'
,
initialize
(
attrs
)
{
this
.
chatroomview
=
attrs
.
chatroomview
;
this
.
listenTo
(
this
.
chatroomview
.
model
.
features
,
'
change:passwordprotected
'
,
this
.
render
);
this
.
listenTo
(
this
.
chatroomview
.
model
.
features
,
'
change:config_stanza
'
,
this
.
render
);
this
.
render
();
},
toHTML
()
{
const
stanza
=
u
.
toStanza
(
this
.
model
.
get
(
'
config_stanza
'
));
const
whitelist
=
api
.
settings
.
get
(
'
roomconfig_whitelist
'
);
let
fields
=
sizzle
(
'
field
'
,
stanza
);
if
(
whitelist
.
length
)
{
fields
=
fields
.
filter
(
f
=>
whitelist
.
includes
(
f
.
getAttribute
(
'
var
'
)));
}
const
password_protected
=
this
.
model
.
features
.
get
(
'
passwordprotected
'
);
const
options
=
{
'
new_password
'
:
!
password_protected
,
'
fixed_username
'
:
this
.
model
.
get
(
'
jid
'
)
};
return
tpl_muc_config_form
({
'
closeConfigForm
'
:
ev
=>
this
.
closeConfigForm
(
ev
),
'
fields
'
:
fields
.
map
(
f
=>
u
.
xForm2webForm
(
f
,
stanza
,
options
)),
'
instructions
'
:
stanza
.
querySelector
(
'
instructions
'
)?.
textContent
,
'
submitConfigForm
'
:
ev
=>
this
.
submitConfigForm
(
ev
),
'
title
'
:
stanza
.
querySelector
(
'
title
'
)?.
textContent
});
},
async
submitConfigForm
(
ev
)
{
ev
.
preventDefault
();
const
inputs
=
sizzle
(
'
:input:not([type=button]):not([type=submit])
'
,
ev
.
target
);
const
config_array
=
inputs
.
map
(
u
.
webForm2xForm
).
filter
(
f
=>
f
);
try
{
await
this
.
model
.
sendConfiguration
(
config_array
);
}
catch
(
e
)
{
log
.
error
(
e
);
const
message
=
__
(
"
Sorry, an error occurred while trying to submit the config form.
"
)
+
"
"
+
__
(
"
Check your browser's developer console for details.
"
);
api
.
alert
(
'
error
'
,
__
(
'
Error
'
),
message
);
}
await
this
.
model
.
refreshDiscoInfo
();
this
.
chatroomview
.
closeForm
();
},
closeConfigForm
(
ev
)
{
ev
.
preventDefault
();
this
.
chatroomview
.
closeForm
();
}
});
export
default
MUCConfigForm
src/plugins/muc-views/index.js
0 → 100644
View file @
e8536ebc
/**
* @module converse-muc-views
* @copyright 2020, the Converse.js contributors
* @description XEP-0045 Multi-User Chat Views
* @license Mozilla Public License (MPLv2)
*/
import
'
../../components/muc-sidebar
'
;
import
'
../chatview/index.js
'
;
import
'
../modal.js
'
;
import
'
@converse/headless/utils/muc
'
;
import
ChatRoomViewMixin
from
'
./muc.js
'
;
import
MUCConfigForm
from
'
./config-form.js
'
;
import
MUCPasswordForm
from
'
./password-form.js
'
;
import
log
from
'
@converse/headless/log
'
;
import
muc_api
from
'
./api.js
'
;
import
{
RoomsPanel
,
RoomsPanelViewMixin
}
from
'
./rooms-panel.js
'
;
import
{
api
,
converse
,
_converse
}
from
'
@converse/headless/core
'
;
const
{
Strophe
}
=
converse
.
env
;
function
setMUCDomain
(
domain
,
controlboxview
)
{
controlboxview
.
getRoomsPanel
().
model
.
save
(
'
muc_domain
'
,
Strophe
.
getDomainFromJid
(
domain
));
}
function
setMUCDomainFromDisco
(
controlboxview
)
{
/* Check whether service discovery for the user's domain
* returned MUC information and use that to automatically
* set the MUC domain in the "Add groupchat" modal.
*/
function
featureAdded
(
feature
)
{
if
(
!
feature
)
{
return
;
}
if
(
feature
.
get
(
'
var
'
)
===
Strophe
.
NS
.
MUC
)
{
feature
.
entity
.
getIdentity
(
'
conference
'
,
'
text
'
).
then
(
identity
=>
{
if
(
identity
)
{
setMUCDomain
(
feature
.
get
(
'
from
'
),
controlboxview
);
}
});
}
}
api
.
waitUntil
(
'
discoInitialized
'
)
.
then
(()
=>
{
api
.
listen
.
on
(
'
serviceDiscovered
'
,
featureAdded
);
// Features could have been added before the controlbox was
// initialized. We're only interested in MUC
_converse
.
disco_entities
.
each
(
entity
=>
featureAdded
(
entity
.
features
.
findWhere
({
'
var
'
:
Strophe
.
NS
.
MUC
})));
})
.
catch
(
e
=>
log
.
error
(
e
));
}
function
fetchAndSetMUCDomain
(
controlboxview
)
{
if
(
controlboxview
.
model
.
get
(
'
connected
'
))
{
if
(
!
controlboxview
.
getRoomsPanel
().
model
.
get
(
'
muc_domain
'
))
{
if
(
api
.
settings
.
get
(
'
muc_domain
'
)
===
undefined
)
{
setMUCDomainFromDisco
(
controlboxview
);
}
else
{
setMUCDomain
(
api
.
settings
.
get
(
'
muc_domain
'
),
controlboxview
);
}
}
}
}
function
openChatRoomFromURIClicked
(
ev
)
{
ev
.
preventDefault
();
api
.
rooms
.
open
(
ev
.
target
.
href
);
}
async
function
addView
(
model
)
{
const
views
=
_converse
.
chatboxviews
;
if
(
!
views
.
get
(
model
.
get
(
'
id
'
))
&&
model
.
get
(
'
type
'
)
===
_converse
.
CHATROOMS_TYPE
&&
model
.
isValid
())
{
await
model
.
initialized
;
return
views
.
add
(
model
.
get
(
'
id
'
),
new
_converse
.
ChatRoomView
({
model
}));
}
}
converse
.
plugins
.
add
(
'
converse-muc-views
'
,
{
/* Dependencies are other plugins which might be
* overridden or relied upon, and therefore need to be loaded before
* this plugin. They are "optional" because they might not be
* available, in which case any overrides applicable to them will be
* ignored.
*
* NB: These plugins need to have already been loaded via require.js.
*
* It's possible to make these dependencies "non-optional".
* If the setting "strict_plugin_dependencies" is set to true,
* an error will be raised if the plugin is not found.
*/
dependencies
:
[
'
converse-autocomplete
'
,
'
converse-modal
'
,
'
converse-controlbox
'
,
'
converse-chatview
'
],
overrides
:
{
ControlBoxView
:
{
renderControlBoxPane
()
{
this
.
__super__
.
renderControlBoxPane
.
apply
(
this
,
arguments
);
if
(
api
.
settings
.
get
(
'
allow_muc
'
))
{
this
.
renderRoomsPanel
();
}
}
}
},
initialize
()
{
const
{
_converse
}
=
this
;
api
.
promises
.
add
([
'
roomsPanelRendered
'
]);
// Configuration values for this plugin
// ====================================
// Refer to docs/source/configuration.rst for explanations of these
// configuration settings.
api
.
settings
.
extend
({
'
auto_list_rooms
'
:
false
,
'
cache_muc_messages
'
:
true
,
'
locked_muc_nickname
'
:
false
,
'
modtools_disable_query
'
:
[],
'
modtools_disable_assign
'
:
false
,
'
muc_disable_slash_commands
'
:
false
,
'
muc_mention_autocomplete_filter
'
:
'
contains
'
,
'
muc_mention_autocomplete_min_chars
'
:
0
,
'
muc_mention_autocomplete_show_avatar
'
:
true
,
'
muc_roomid_policy
'
:
null
,
'
muc_roomid_policy_hint
'
:
null
,
'
roomconfig_whitelist
'
:
[],
'
show_retraction_warning
'
:
true
,
'
visible_toolbar_buttons
'
:
{
'
toggle_occupants
'
:
true
}
});
_converse
.
MUCConfigForm
=
MUCConfigForm
;
_converse
.
MUCPasswordForm
=
MUCPasswordForm
;
_converse
.
ChatRoomView
=
_converse
.
ChatBoxView
.
extend
(
ChatRoomViewMixin
);
_converse
.
RoomsPanel
=
RoomsPanel
;
_converse
.
ControlBoxView
&&
Object
.
assign
(
_converse
.
ControlBoxView
.
prototype
,
RoomsPanelViewMixin
);
Object
.
assign
(
_converse
.
api
,
muc_api
);
/************************ BEGIN Event Handlers ************************/
api
.
listen
.
on
(
'
chatBoxViewsInitialized
'
,
()
=>
{
_converse
.
chatboxviews
.
delegate
(
'
click
'
,
'
a.open-chatroom
'
,
openChatRoomFromURIClicked
);
_converse
.
chatboxes
.
on
(
'
add
'
,
addView
);
});
api
.
listen
.
on
(
'
clearSession
'
,
()
=>
{
const
view
=
_converse
.
chatboxviews
.
get
(
'
controlbox
'
);
if
(
view
&&
view
.
roomspanel
)
{
view
.
roomspanel
.
model
.
destroy
();
view
.
roomspanel
.
remove
();
delete
view
.
roomspanel
;
}
});
api
.
listen
.
on
(
'
controlBoxInitialized
'
,
view
=>
{
if
(
!
api
.
settings
.
get
(
'
allow_muc
'
))
{
return
;
}
fetchAndSetMUCDomain
(
view
);
view
.
model
.
on
(
'
change:connected
'
,
()
=>
fetchAndSetMUCDomain
(
view
));
});
/************************ END Event Handlers ************************/
}
});
src/plugins/muc-views.js
→
src/plugins/muc-views
/muc
.js
View file @
e8536ebc
This diff is collapsed.
Click to expand it.
src/plugins/muc-views/password-form.js
0 → 100644
View file @
e8536ebc
import
tpl_muc_password_form
from
"
templates/muc_password_form.js
"
;
import
{
View
}
from
'
@converse/skeletor/src/view.js
'
;
const
MUCPasswordForm
=
View
.
extend
({
className
:
'
chatroom-form-container muc-password-form
'
,
initialize
(
attrs
)
{
this
.
chatroomview
=
attrs
.
chatroomview
;
this
.
listenTo
(
this
.
model
,
'
change:validation_message
'
,
this
.
render
);
this
.
render
();
},
toHTML
()
{
return
tpl_muc_password_form
({
'
jid
'
:
this
.
model
.
get
(
'
jid
'
),
'
submitPassword
'
:
ev
=>
this
.
submitPassword
(
ev
),
'
validation_message
'
:
this
.
model
.
get
(
'
validation_message
'
)
});
},
submitPassword
(
ev
)
{
ev
.
preventDefault
();
const
password
=
this
.
el
.
querySelector
(
'
input[type=password]
'
).
value
;
this
.
chatroomview
.
model
.
join
(
this
.
chatroomview
.
model
.
get
(
'
nick
'
),
password
);
this
.
model
.
set
(
'
validation_message
'
,
null
);
}
});
export
default
MUCPasswordForm
;
src/plugins/muc-views/rooms-panel.js
0 → 100644
View file @
e8536ebc
import
AddMUCModal
from
'
modals/add-muc.js
'
;
import
tpl_room_panel
from
'
templates/room_panel.js
'
;
import
{
View
}
from
'
@converse/skeletor/src/view.js
'
;
import
MUCListModal
from
'
modals/muc-list.js
'
;
import
{
_converse
,
api
,
converse
}
from
'
@converse/headless/core
'
;
import
{
__
}
from
'
i18n
'
;
const
u
=
converse
.
env
.
utils
;
/**
* View which renders MUC section of the control box.
* @class
* @namespace _converse.RoomsPanel
* @memberOf _converse
*/
export
const
RoomsPanel
=
View
.
extend
({
tagName
:
'
div
'
,
className
:
'
controlbox-section
'
,
id
:
'
chatrooms
'
,
events
:
{
'
click a.controlbox-heading__btn.show-add-muc-modal
'
:
'
showAddRoomModal
'
,
'
click a.controlbox-heading__btn.show-list-muc-modal
'
:
'
showMUCListModal
'
},
toHTML
()
{
return
tpl_room_panel
({
'
heading_chatrooms
'
:
__
(
'
Groupchats
'
),
'
title_new_room
'
:
__
(
'
Add a new groupchat
'
),
'
title_list_rooms
'
:
__
(
'
Query for groupchats
'
)
});
},
showAddRoomModal
(
ev
)
{
api
.
modal
.
show
(
AddMUCModal
,
{
'
model
'
:
this
.
model
},
ev
);
},
showMUCListModal
(
ev
)
{
api
.
modal
.
show
(
MUCListModal
,
{
'
model
'
:
this
.
model
},
ev
);
}
});
/**
* Mixin which adds the ability to a ControlBox to render a list of open groupchats
* @mixin
*/
export
const
RoomsPanelViewMixin
=
{
renderRoomsPanel
()
{
if
(
this
.
roomspanel
&&
u
.
isInDOM
(
this
.
roomspanel
.
el
))
{
return
this
.
roomspanel
;
}
const
id
=
`converse.roomspanel
${
_converse
.
bare_jid
}
`
;
this
.
roomspanel
=
new
_converse
.
RoomsPanel
({
'
model
'
:
new
(
_converse
.
RoomsPanelModel
.
extend
({
id
,
'
browserStorage
'
:
_converse
.
createStore
(
id
)
}))()
});
this
.
roomspanel
.
model
.
fetch
();
this
.
el
.
querySelector
(
'
.controlbox-pane
'
).
insertAdjacentElement
(
'
beforeEnd
'
,
this
.
roomspanel
.
render
().
el
);
/**
* Triggered once the section of the { @link _converse.ControlBoxView }
* which shows gropuchats has been rendered.
* @event _converse#roomsPanelRendered
* @example _converse.api.listen.on('roomsPanelRendered', () => { ... });
*/
api
.
trigger
(
'
roomsPanelRendered
'
);
return
this
.
roomspanel
;
},
getRoomsPanel
()
{
if
(
this
.
roomspanel
&&
u
.
isInDOM
(
this
.
roomspanel
.
el
))
{
return
this
.
roomspanel
;
}
else
{
return
this
.
renderRoomsPanel
();
}
}
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment