This commit is contained in:
nnduc
2026-10-24 14:03:52 +07:00
commit 4fe046de58
4790 changed files with 311146 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
[chatrooms]
autojoin = Join this chatroom on login
avatar = Change the chatroom avatar
bad_id = Bad Chatroom Address
bad_nickname = Please enter a valid nickname (2 to 40 characters)
banned = Banned
conference_call = Conference call
conference_call_edit = Edit the conference call
conference_call_text = Call your contacts and share your webcam or screen
config = Configuration
config_saved = Configuration saved
configure = Configure the chatroom
conflict = Nickname already taken
connected = Joined the chatroom
create = Create a chatroom
created = Chatroom created
default_room = Standard chatroom
destroy_text = Are you sure you want to permanently destroy the following chatroom?
destroy_title = Destroy the chatroom
destroyed = Chatroom destroyed
disco_error = Movim was not able to find a valid chatroom. Try maybe with another identifier.
disco_maybe_space = This chatroom seems to be part of a Space, we are not able to find which one but we strongly advise you to join the Space instead
disco_not_muc = You are trying to add something that is not a chatroom
disco_registration_required = A registration is required before using the service
disconnected = Left the chatroom
discover = Discover a chatroom
edit = Edit the chatroom
empty_name = Empty name
empty_text1 = You don’t have any chatroom yet.
empty_text2 = Add one by clicking on the add button.
explore_placeholder = Name or description
filter_all = All
filter_connected = Connected
first_room_placeholder = Press the %s button to add a first chatroom
forbidden = You are not allowed to join this chatroom
gateway_room = Gateway chatroom
hide_disconnected = Hide disconnected chatrooms
id = Chatroom Address
itemnotfound = The chatroom doesn’t exist
jidmalformed = Your nickname is not valid
join = Join a chatroom
join_custom = Join a custom chatroom
members = Members
name_placeholder = My Favorite Chatroom
notacceptable = Not acceptable
notallowed = You are not allowed to create a chatroom there
notauthorized = A password is required
pinned = Pin this chatroom
registrationrequired = Chatroom cannot be joined, registration required
remoteservernotfound = The remote server for this chatroom doesn’t exist
remoteservertimeout = Connection to remote server timed out
remove_text = You are going to permanently leave the following chatroom. Please confirm your action.
remove_title = Permanently leave a chatroom
serviceunavailable = The chatroom participant limit has been reached
show_all = Show all chatrooms
subject = Subject
title = Chatrooms
type_room = Type of chatroom
users = Users
[bookmarks]
updated = Bookmarks updated
[room]
anonymous_title = Public Channel
anonymous_text1 = You are currently logged as an anonymous user.
anonymous_text2 = You can join using your own account or create one on the login page by logging out using the cross in the top-right corner.
anonymous_login = Login on %s
invite = Invite a contact
invited = Invitation sent
invite_code = Send this link to your contacts
public_muc = Public
public_muc_text = This chatroom is publicly discoverable
nonanonymous_muc = Public profiles
nonanonymous_muc_text = "The participants of this chatroom can see each other's XMPP Addresses"
archived = Archived
archived_text = The chatroom messages are archived
group_chat = Group Chat
group_chat_text = Private group chat with invited members
group_chat_add = Add a new member
group_chat_remove = Remove a member
group_chat_remove_text = You will remove the following member, are you sure?
banned_add = Ban someone
banned_remove = Unban
configure_user = Configure the user
change_affiliation_unauthorized = You are not authorized to change this affiliation
affiliation = Affiliation
role = Role
reason = Reason
channel = Channel
channel_text = Public channel that can be publicly discoverable and joinable
notify_title = Notifications
notify_never = Never notify
notify_mentioned = Notify when mentioned
notify_always = Always notify
pinned = Pinned
affiliation_owners = Owners
affiliation_admins = Admins
visitor = Visitor
allowed_send_messages = Is the user allowed to send messages?
role_changed = Role changed
+124
View File
@@ -0,0 +1,124 @@
#rooms {
animation: fadeIn 0.5s;
display: flex;
flex-direction: column;
}
#rooms[data-scroll] li.subheader:first-child {
animation: backgroundBlink 1s;
}
#rooms>ul.list>li i.call {
margin-right: 0.75rem;
}
#rooms>ul.list {
order: 1;
}
#rooms>ul.list.head {
order: 0;
}
#rooms ul li.room {
white-space: nowrap;
overflow-x: hidden;
}
#gateway_rooms:empty {
min-height: 0;
}
#gateway_rooms:not(:empty)+div {
display: none;
}
#rooms ul.list.rooms li:not(.connecting) li span.control.connecting {
display: none;
}
#rooms ul.list.rooms li span.control.edition {
position: absolute;
display: block;
right: -7rem;
margin: 0;
width: 5.5rem;
background-color: rgb(var(--movim-background));
top: 0;
height: 5.25rem;
line-height: 5.25rem;
box-shadow: var(--elevation-1);
transition: right 0.2s var(--accelerate-easing);
}
#rooms ul.list.rooms li:hover span.control.edition {
right: 0;
transition: right 0.2s var(--decelerate-easing) 0.75s;
}
#rooms ul.list.rooms {
display: flex;
flex-direction: column;
}
#rooms ul.list.rooms>li:not(.connected) span.primary {
opacity: 0.25;
filter: grayscale(0.5);
}
#rooms ul.toggle_show li div>p:first-child {
line-height: initial;
}
#rooms ul.toggle_show li div>p {
line-height: 2.5rem;
font-size: 1.75rem;
color: rgba(var(--movim-font), 0.6);
}
#rooms ul.list.rooms:empty~ul.toggle_show,
#rooms ul.list.rooms:not(:empty):not(.all)~ul.toggle_show>li span.primary i:first-child,
#rooms ul.list.rooms:not(:empty).all~ul.toggle_show>li span.primary i:last-child,
#rooms ul.list.rooms:not(:empty):not(.all)~ul.list.head>li span.control.toggle_show i:first-child,
#rooms ul.list.rooms:not(:empty).all~ul.list.head>li span.control.toggle_show i:last-child,
#rooms ul.list.rooms:not(:empty):not(.all)~ul.toggle_show>li div>p:first-child,
#rooms ul.list.rooms:not(:empty).all~ul.toggle_show>li div>p:last-child,
#rooms ul.list.rooms:not(:empty)~ul.empty,
#rooms ul.list.rooms:not(.different_states)~ul.toggle_show,
#rooms ul.list.rooms:not(.all)>li:not(.connected) {
display: none;
}
/* Rooms order */
#rooms>ul.list.rooms>li {
order: 4;
}
#rooms>ul.list.rooms>li.groupchat {
order: 3;
}
#rooms>ul.list.rooms>li.pinned {
order: 2;
}
#rooms>ul.list.rooms>li.unread {
order: 1;
}
#rooms>ul.list.rooms>li.connected {
order: 0;
}
#rooms>ul.list.rooms>li.connected.groupchat {
order: -1;
}
#rooms>ul.list.rooms>li.connected.pinned {
order: -2;
}
#rooms>ul.list.rooms>li.connected.unread {
order: -3;
}
+262
View File
@@ -0,0 +1,262 @@
var Rooms = {
default_services: [],
refreshMujisInterval: null,
cleanId: function (input) {
if (input.value) {
if (input.value.substring(0, 5) == 'xmpp:') {
input.value = input.value.substring(5);
}
if (input.value.slice(-5) == '?join') {
input.value = input.value.slice(0, -5);
}
}
},
setDefaultServices: function (services) {
Rooms.default_services = services;
},
toggleScroll: function () {
var chats = document.querySelector('#chats_widget_header');
var rooms = document.querySelector('#rooms');
if (rooms.dataset.scroll) {
chats.scrollIntoView();
} else {
rooms.scrollIntoView();
}
},
scrollToChats: function () {
var chats = document.querySelector('#chats_widget_header');
var rooms = document.querySelector('#rooms');
var chatcounter = document.querySelector('#chatcounter i');
var bottomchatcounter = document.querySelector('#bottomchatcounter i');
chats.dataset.scroll = true;
delete rooms.dataset.scroll;
chatcounter.innerHTML = bottomchatcounter.innerHTML = 'chat_bubble';
},
scrollToRooms: function () {
var chats = document.querySelector('#chats_widget_header');
var rooms = document.querySelector('#rooms');
var chatcounter = document.querySelector('#chatcounter i');
var bottomchatcounter = document.querySelector('#bottomchatcounter i');
delete chats.dataset.scroll;
rooms.dataset.scroll = true;
chatcounter.innerHTML = bottomchatcounter.innerHTML = 'forum';
},
checkNoConnected: function () {
if (
!document.querySelector('#rooms ul.list.rooms li.connected')
&& localStorage.getItem('rooms_all') == 'true'
&& document.querySelector('#rooms ul.list.rooms')
) {
document.querySelector('#rooms ul.list.rooms').classList.add('all');
}
},
toggleShowAll: function () {
document.querySelector('#rooms ul.list.rooms').classList.toggle('all');
localStorage.setItem('rooms_all', document.querySelector('#rooms ul.list.rooms').classList.contains('all'));
Rooms.displayToggleButton();
},
displayToggleButton: function () {
document.querySelectorAll('#rooms span.chip').forEach(chip => {
chip.classList.remove('enabled');
});
if (localStorage.getItem('rooms_all') == 'true') {
document.querySelector('#rooms span.chip[data-filter=all]')?.classList.add('enabled');
} else {
document.querySelector('#rooms span.chip[data-filter=connected]')?.classList.add('enabled');
}
},
selectGatewayRoom: function (room) {
document.querySelector('form[name="rooms_discover"] input[name=jid]').value = room;
RoomsUtils_ajaxDiscoRoom(room);
MovimUtils.addClass('#rooms_discover_add', 'disabled');
},
setJid: function (slugifiedJid) {
let input = document.querySelector('form[name=bookmarkmucadd] input[name=jid]');
if (input && input.value === '') {
input.value = slugifiedJid;
}
},
suggest: function () {
let input = document.querySelector('form[name=bookmarkmucadd] input[name=jid]');
if (input && input.value != '' && !input.value.includes('@')) {
let suggestions = document.querySelector('datalist#suggestions');
if (suggestions) {
suggestions.textContent = '';
Rooms.default_services.forEach(function (item) {
var option = document.createElement('option');
option.value = input.value + '@' + item.server;
suggestions.appendChild(option);
});
}
}
},
refresh: function () {
Rooms.displayToggleButton();
var parent = document.querySelector('#rooms').parentElement;
parent.onscroll = e => {
if ((e.target.scrollHeight <= e.target.scrollTop + e.target.offsetHeight + 1)
|| (e.target.scrollTop + 5 >= document.querySelector('#rooms').offsetTop)) {
Rooms.scrollToRooms();
} else {
Rooms.scrollToChats();
}
};
var list = document.querySelector('#rooms ul.list.rooms');
var items = document.querySelectorAll('#rooms ul.list.rooms li:not(.subheader)');
var i = 0;
var differentStates = false;
list.classList.remove('different_states');
while (i < items.length) {
if (items[i].dataset.jid != null) {
items[i].onclick = function (e) {
Chat.getRoom(this.dataset.jid);
}
if (MovimUtils.isMobile()) {
let touchTimer;
let moveX = 0;
let moveY = 0;
items[i].ontouchstart = function (event) {
touchTimer = setTimeout(() => {
touchTimer = null;
if (moveX == 0 && moveY == 0) {
RoomsUtils_ajaxAdd(this.dataset.jid);
}
}, 500);
}
items[i].ontouchmove = function (event) {
moveX += Math.abs(event.targetTouches[0].pageX);
moveY += Math.abs(event.targetTouches[0].pageY);
}
items[i].ontouchend = function (event) {
clearTimeout(touchTimer);
moveX = moveY = 0;
}
}
}
if (
i >= 1
&& !differentStates
&& items[i - 1].classList.contains('connected') != items[i].classList.contains('connected')
) {
differentStates = true;
}
items[i].classList.remove('active');
i++;
}
if (differentStates) {
list.classList.add('different_states');
} else {
Rooms.checkNoConnected();
}
},
clearRooms: function () {
if (rooms = document.querySelector('#rooms ul.list.rooms')) {
rooms.innerHTML = '';
}
},
setRoom: function (id, html) {
var listSelector = '#rooms ul.list.rooms ';
var list = document.querySelector(listSelector);
if (list) {
var element = list.querySelector('#' + id);
if (element) element.remove();
var rooms = document.querySelectorAll(listSelector + '> li');
var i = 0;
while (i < rooms.length) {
if (rooms[i].id > id) {
MovimTpl.prependBefore(listSelector + '#' + rooms[i].id, html);
break;
}
i++;
}
if (i == rooms.length) {
MovimTpl.append(listSelector, html);
}
}
},
clearAllActives: function () {
document.querySelectorAll('#rooms ul.list.rooms li:not(.subheader)')
.forEach(item => item.classList.remove('active'));
},
setActive: function (jid) {
Chats.clearAllActives();
Rooms.clearAllActives();
MovimUtils.addClass('#rooms ul.list.rooms li[data-jid="' + jid + '"]', 'active');
},
setUnread: function (id, unread) {
var element = document.querySelector('#rooms ul.list.rooms #' + id);
if (element) {
if (unread) {
element.classList.add('unread');
} else {
element.classList.remove('unread');
}
}
},
refreshMujis: function () {
// Doesn't refresh the list while we're on it
document.querySelectorAll('#rooms li.muji:not(.active)').forEach(room => {
Rooms_ajaxRefresh(room.dataset.jid);
});
}
}
MovimWebsocket.initiate(() => {
clearInterval(Rooms.refreshMujisInterval);
Rooms.refreshMujisInterval = setInterval(Rooms.refreshMujis, 15 * 1000);
Rooms_ajaxHttpGet();
Rooms.checkNoConnected();
});