build: modernize WebUI build and lint tooling

This commit is contained in:
Sumit Kumar Soni 2026-08-02 20:46:00 +05:30
parent f0cb7e1c83
commit 35c5c17309
28 changed files with 1568 additions and 883 deletions

View File

@ -1,57 +0,0 @@
{
"root": true,
"env": {
"browser": true,
"commonjs": true,
"es6": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly",
"window": "readonly",
"document": "readonly"
},
"parserOptions": {
"ecmaVersion": 2020
},
"ignorePatterns": ["mithril.js", "assets/*", "make-src/*"],
"rules": {
"linebreak-style": ["off", "unix"],
"quotes": ["error", "single"],
"semi": ["error", "always"],
"arrow-spacing": ["error", { "before": true, "after": true }],
"arrow-parens": ["error", "always"],
"comma-style": ["error", "last"],
"comma-spacing": ["error", { "before": false, "after": true }],
"camelcase": [
"error",
{
"allow": ["^UNSAFE_"],
"properties": "never",
"ignoreGlobals": true
}
],
"eol-last": "error",
"eqeqeq": ["error", "always", { "null": "ignore" }],
"no-irregular-whitespace": ["error"],
"no-trailing-spaces": ["error"],
"no-unexpected-multiline": ["error"],
"no-unreachable": ["error"],
"no-var": "warn",
"no-unused-vars": [
"error",
{
"args": "none",
"caughtErrors": "none",
"ignoreRestSiblings": true,
"vars": "all"
}
],
"no-use-before-define": ["warn", { "functions": true, "classes": false }],
"object-shorthand": "error",
"prefer-const": ["error", { "destructuring": "all" }],
"semi-style": ["warn", "last"],
"spaced-comment": ["warn", "always"]
}
}

1
webui-src/.nvmrc Normal file
View File

@ -0,0 +1 @@
v24.15.0

View File

@ -39,7 +39,7 @@ function createboard() {
m('label[for=thumbnail]', 'Thumbnail: '),
m('input[type=file][name=files][id=thumbnail][accept=image/*]', {
onchange: async (e) => {
let reader = new FileReader();
const reader = new FileReader();
reader.onloadend = function () {
thumbnail = reader.result.substring(reader.result.indexOf(',') + 1);
};

View File

@ -1,17 +1,17 @@
const m = require('mithril');
const rs = require('rswebui');
const GROUP_SUBSCRIBE_ADMIN = 0x01;// means: you have the admin key for this group
const GROUP_SUBSCRIBE_PUBLISH = 0x02;// means: you have the publish key for thiss group. Typical use: publish key in channels are shared with specific friends.
const GROUP_SUBSCRIBE_SUBSCRIBED = 0x04;// means: you are subscribed to a group, which makes you a source for this group to your friend nodes.
const GROUP_SUBSCRIBE_ADMIN = 0x01; // means: you have the admin key for this group
const GROUP_SUBSCRIBE_PUBLISH = 0x02; // means: you have the publish key for thiss group. Typical use: publish key in channels are shared with specific friends.
const GROUP_SUBSCRIBE_SUBSCRIBED = 0x04; // means: you are subscribed to a group, which makes you a source for this group to your friend nodes.
const GROUP_SUBSCRIBE_NOT_SUBSCRIBED = 0x08;
const GROUP_MY_BOARD = GROUP_SUBSCRIBE_ADMIN + GROUP_SUBSCRIBE_SUBSCRIBED + GROUP_SUBSCRIBE_PUBLISH;
const GXS_VOTE_DOWN = 0x0001;
const GXS_VOTE_UP = 0x0002;
//rsgxscircles.h:50
const PUBLIC = 1; /// Public distribution
const EXTERNAL = 2; /// Restricted to an external circle, based on GxsIds
// rsgxscircles.h:50
const PUBLIC = 1; // Public distribution
const EXTERNAL = 2; // Restricted to an external circle, based on GxsIds
const NODES_GROUP = 3;
const Data = {
@ -20,34 +20,6 @@ const Data = {
Comments: {}, // threadID, msgID -> {Comment, showReplies}
};
async function updateContent(content, boardid) {
const res = await rs.rsJsonApiRequest('/rsPosted/getBoardContent', {
boardId: boardid,
contentsIds: [content.mMsgId],
});
if (res.body.retval && res.body.posts.length > 0) {
Data.Posts[boardid][content.mMsgId] = { post: res.body.posts[0], isSearched: true };
} else if (res.body.retval && res.body.comments.length > 0) {
if (Data.Comments[content.mThreadId] === undefined) {
Data.Comments[content.mThreadId] = {};
}
Data.Comments[content.mThreadId][content.mMsgId] = res.body.comments[0];
} else if (res.body.retval && res.body.votes.length > 0) {
const vote = res.body.votes[0];
if (
Data.Comments[vote.mMeta.mThreadId] &&
Data.Comments[vote.mMeta.mThreadId][vote.mMeta.mParentId]
) {
if (vote.mVoteType === GXS_VOTE_UP) {
Data.Comments[vote.mMeta.mThreadId][vote.mMeta.mParentId].mUpVotes += 1;
}
if (vote.mVoteType === GXS_VOTE_DOWN) {
Data.Comments[vote.mMeta.mThreadId][vote.mMeta.mParentId].mDownVotes += 1;
}
}
}
}
async function updateDisplayBoards(keyid, details) {
const res1 = await rs.rsJsonApiRequest('/rsPosted/getBoardsInfo', {
boardsIds: [keyid],
@ -72,7 +44,7 @@ async function updateDisplayBoards(keyid, details) {
Data.Posts[keyid] = {};
}
/*const res2 = await rs.rsJsonApiRequest('/rsPosted/getContentSummaries', {
/* const res2 = await rs.rsJsonApiRequest('/rsPosted/getContentSummaries', {
boardId: keyid,
});
@ -81,7 +53,6 @@ async function updateDisplayBoards(keyid, details) {
updateContent(content, keyid);
});
}*/
}
const DisplayBoardsFromList = () => {

View File

@ -109,7 +109,7 @@ function createchannel() {
m('label[for=thumbnail]', 'Thumbnail: '),
m('input[type=file][name=files][id=thumbnail][accept=image/*]', {
onchange: async (e) => {
let reader = new FileReader();
const reader = new FileReader();
reader.onloadend = function () {
thumbnail = reader.result.substring(reader.result.indexOf(',') + 1);
};
@ -238,7 +238,7 @@ const AddPost = () => {
m('label[for=thumbnail]', 'Thumbnail: '),
m('input[type=file][name=files][id=thumbnail][accept=image/*]', {
onchange: async (e) => {
let reader = new FileReader();
const reader = new FileReader();
reader.onloadend = function () {
pthumbnail = reader.result.substring(reader.result.indexOf(',') + 1);
};

View File

@ -7,18 +7,11 @@ const chatEmoji = require('chat/chat_emoji');
const HistoryBrowserModal = require('people/people_history');
const {
get64Num,
loadLobbyDetails,
loadDistantChatDetails,
sortLobbies,
getNicknameColor,
getStatusColor,
getStatusTooltip,
renderTextWithEmoji,
getSafeAvatar,
MobileState,
ChatRoomsModel,
Message,
ChatLobbyModel,
ChatHubState,
} = chatState;
@ -123,13 +116,13 @@ function pollHashStatus(localpath) {
const info = data.info;
const sizeNum = info.size.xint64 || parseInt(info.size.xstr64) || info.size;
const fileLink = `<a href="retroshare://file?name=${encodeURIComponent(info.name)}&size=${sizeNum}&hash=${info.hash}">${info.name}</a> (${rs.formatBytes(sizeNum)})`;
const textarea = document.querySelector('.chat-hub-textarea');
if (textarea) {
const val = textarea.value;
textarea.value = val ? val + '\n' + fileLink : fileLink;
}
ChatHubState.showAttachModal = false;
ChatHubState.isHashing = false;
ChatHubState.attachPath = '';
@ -144,75 +137,6 @@ function pollHashStatus(localpath) {
// ************************* views ****************************
const Lobby = () => {
return {
view: (vnode) => {
const { info, tagname, onclick, lobbytagname = 'mainname' } = vnode.attrs;
return m(
ChatLobbyModel.selected(info, '.selected-lobby', tagname),
{
key: rs.idToHex(info.lobby_id),
onclick,
},
[
m('h5', { class: lobbytagname }, info.lobby_name === '' ? '<unnamed>' : info.lobby_name),
m('.topic', info.lobby_topic),
]
);
},
};
};
const LobbyList = {
view(vnode) {
const tagname = vnode.attrs.tagname;
const lobbytagname = vnode.attrs.lobbytagname;
const onclick = vnode.attrs.onclick || (() => null);
return [
vnode.attrs.rooms.map((info) =>
m(Lobby, {
info,
tagname,
lobbytagname,
onclick: onclick(info),
})
),
];
},
};
const SubscribedLobbies = {
view() {
return m('.widget', [
m('.widget__heading', m('h3', 'Subscribed chat rooms')),
m('.widget__body', [
m(LobbyList, {
rooms: sortLobbies(Object.values(ChatRoomsModel.subscribedRooms)),
tagname: '.lobby.subscribed',
onclick: ChatLobbyModel.switchToEvent,
}),
]),
]);
},
};
const PublicLobbies = {
view() {
return m('.widget', [
m('.widget__heading', m('h3', 'Public chat rooms')),
m('.widget__body', [
m(LobbyList, {
rooms: (ChatRoomsModel.allRooms || []).filter((info) => !ChatRoomsModel.subscribed(info)),
tagname: '.lobby.public',
onclick: ChatLobbyModel.setupEvent,
}),
]),
]);
},
};
// ************************* Chat Hub Sub-Components ****************************
const ChatRoomHeader = () => {
return {
view: (vnode) => {
@ -982,8 +906,6 @@ const ChatRoomDetailView = () => {
const room = ChatHubState.selectedRoom;
if (!room) return null;
let participantCount = 0;
let participantNames = [];
let participants = [];
if (room.gxs_ids) {
@ -994,7 +916,7 @@ const ChatRoomDetailView = () => {
}));
} else if (typeof room.gxs_ids === 'object') {
participants = Object.keys(room.gxs_ids).map((key) => ({
key: key,
key,
name: rs.userList.username(key) || key
}));
}
@ -1011,8 +933,8 @@ const ChatRoomDetailView = () => {
}
}
participantCount = participants.length;
participantNames = participants.map((p) => p.name);
const participantCount = participants.length;
const participantNames = participants.map((p) => p.name);
participantNames.sort((a, b) => a.localeCompare(b));
const lobbyHexId = rs.idToHex(room.lobby_id);
@ -1316,7 +1238,7 @@ const Layout = {
ChatHubState.showCreateRoomModal && m('.attach-modal-overlay', [
m('.attach-modal', [
m('h4', 'Create New Chat Room'),
m('.form-field', { style: 'display: flex; flex-direction: column; gap: 0.25rem;' }, [
m('label', { style: 'font-weight: bold; font-size: 0.9rem; color: #475569;' }, 'Room Name:'),
m('input[type=text]', {
@ -1326,7 +1248,7 @@ const Layout = {
style: 'padding: 0.5rem; border: 1px solid #cbd5e1; border-radius: 0.25rem; font-size: 0.9rem;'
})
]),
m('.form-field', { style: 'display: flex; flex-direction: column; gap: 0.25rem; margin-top: 0.5rem;' }, [
m('label', { style: 'font-weight: bold; font-size: 0.9rem; color: #475569;' }, 'Topic:'),
m('input[type=text]', {
@ -1344,7 +1266,7 @@ const Layout = {
onchange: (e) => { ChatHubState.newRoomIdentity = e.target.value; },
style: 'padding: 0.5rem; border: 1px solid #cbd5e1; border-radius: 0.25rem; font-size: 0.9rem; background-color: #ffffff;'
}, [
ChatHubState.ownGxsIdentities && ChatHubState.ownGxsIdentities.map(id => {
ChatHubState.ownGxsIdentities && ChatHubState.ownGxsIdentities.map((id) => {
const details = ChatHubState.gxsDetails[id];
const name = details ? (details.mNickname || details.mGroupName) : id;
return m('option', { value: id }, name);
@ -1386,7 +1308,7 @@ const Layout = {
let flags = 0;
if (isPublic) flags |= 4;
if (isSigned) flags |= 8;
rs.rsJsonApiRequest('/rsChats/createChatLobby', {
lobby_name: name,
lobby_identity: identity,
@ -1601,74 +1523,6 @@ const Layout = {
},
};
const LayoutSingle = () => {
const onResize = () => {
const element = document.querySelector('.messages');
if (element) element.scrollTop = element.scrollHeight;
};
return {
oninit: () => {
ChatLobbyModel.loadLobby(m.route.param('lobby'));
window.addEventListener('resize', onResize);
},
onremove: () => window.removeEventListener('resize', onResize),
view: (vnode) => {
const chatType = ChatLobbyModel.currentLobby.chatType;
const isPrivate = chatType === 1 || chatType === 2;
const isRoom = chatType === 3;
return m(
'.node-panel.chat-panel.chat-room',
{
class:
(MobileState.showLobbies ? 'show-lobbies ' : '') +
(MobileState.showUsers ? 'show-users ' : '') +
(isPrivate ? 'no-lobbies' : ''),
},
[
m('.chat-overlay', { onclick: () => MobileState.closeAll() }),
m(
'.messages' + (isRoom ? '.compact-container' : ''),
{ onclick: () => MobileState.closeAll() },
ChatLobbyModel.messages
),
m(
'.chatMessage',
{},
[
m('textarea.chatMsg', {
placeholder: 'Type a message...',
enterkeyhint: 'send',
onkeydown: (e) => {
if ((e.key === 'Enter' || e.keyCode === 13) && !e.shiftKey) {
const msg = e.target.value;
if (msg.trim() === '') return false;
e.target.value = ' sending ... ';
ChatLobbyModel.sendMessage(msg, () => (e.target.value = ''));
return false;
}
},
}),
m(
'button.chat-send-btn',
{
onclick: (e) => {
const textarea = e.target.closest('.chatMessage').querySelector('textarea');
const msg = textarea.value;
if (msg.trim() === '') return;
textarea.value = ' sending ... ';
ChatLobbyModel.sendMessage(msg, () => (textarea.value = ''));
},
},
m('i.fas.fa-paper-plane')
),
]
),
]
);
},
};
};
/*
/rsChats/initiateDistantChatConnexion
* @param[in] to_pid RsGxsId to start the connection

View File

@ -7,72 +7,72 @@ const EMOJI_ICONS = {
};
const EMOJI_DATA = {
Smileys: [
'😀','😁','😂','🤣','😃','😄','😅','😆','😉','😊','😋','😎','😍','😘','🥰','😗','😙','😚',
'🙂','🤗','🤩','🤔','🤨','😐','😑','😶','🙄','😏','😣','😥','😮','🤐','😯','😪','😫','🥱',
'😴','😌','😛','😜','😝','🤤','😒','😓','😔','😕','🙃','🤑','😲','☹️','🙁','😖','😞','😟',
'😤','😢','😭','😦','😧','😨','😩','🤯','😬','😰','😱','🥵','🥶','😳','🤪','😵','😡','😠',
'🤬','😷','🤒','🤕','🤢','🤮','🤧','🥴','😇','🥳','🥺','🤠','🤡','🤥','🤫','🤭','🧐','🤓',
'😈','👿','👹','👺','💀','☠️','👻','👽','👾','🤖','😺','😸','😹','😻','😼','😽','🙀','😿','😾',
'😀', '😁', '😂', '🤣', '😃', '😄', '😅', '😆', '😉', '😊', '😋', '😎', '😍', '😘', '🥰', '😗', '😙', '😚',
'🙂', '🤗', '🤩', '🤔', '🤨', '😐', '😑', '😶', '🙄', '😏', '😣', '😥', '😮', '🤐', '😯', '😪', '😫', '🥱',
'😴', '😌', '😛', '😜', '😝', '🤤', '😒', '😓', '😔', '😕', '🙃', '🤑', '😲', '☹️', '🙁', '😖', '😞', '😟',
'😤', '😢', '😭', '😦', '😧', '😨', '😩', '🤯', '😬', '😰', '😱', '🥵', '🥶', '😳', '🤪', '😵', '😡', '😠',
'🤬', '😷', '🤒', '🤕', '🤢', '🤮', '🤧', '🥴', '😇', '🥳', '🥺', '🤠', '🤡', '🤥', '🤫', '🤭', '🧐', '🤓',
'😈', '👿', '👹', '👺', '💀', '☠️', '👻', '👽', '👾', '🤖', '😺', '😸', '😹', '😻', '😼', '😽', '🙀', '😿', '😾',
],
People: [
'👋','🤚','🖐️','✋','🖖','👌','🤌','🤏','✌️','🤞','🤟','🤘','🤙','👈','👉','👆','🖕','👇',
'☝️','👍','👎','✊','👊','🤛','🤜','👏','🙌','👐','🤲','🤝','🙏','✍️','💅','🤳','💪','🦾',
'🦿','🦵','🦶','👂','🦻','👃','🫀','🫁','🧠','🦷','🦴','👀','👁️','👅','👄','🫦','👶','🧒',
'👦','👧','🧑','👱','👨','🧔','👩','🧓','👴','👵','🙍','🙎','🙅','🙆','💁','🙋','🧏','🙇',
'🤦','🤷','👮','🕵️','💂','🥷','👷','🫅','🤴','👸','👲','🧕','🤵','👰','🤰','🫃','🫄','🤱',
'👼','🎅','🤶','🧑‍🎄','🦸','🦹','🧙','🧝','🧛','🧟','🧞','🧜','🧚','🧑‍🤝‍🧑','👫','👬','👭','💏','💑','👪',
'👋', '🤚', '🖐️', '✋', '🖖', '👌', '🤌', '🤏', '✌️', '🤞', '🤟', '🤘', '🤙', '👈', '👉', '👆', '🖕', '👇',
'☝️', '👍', '👎', '✊', '👊', '🤛', '🤜', '👏', '🙌', '👐', '🤲', '🤝', '🙏', '✍️', '💅', '🤳', '💪', '🦾',
'🦿', '🦵', '🦶', '👂', '🦻', '👃', '🫀', '🫁', '🧠', '🦷', '🦴', '👀', '👁️', '👅', '👄', '🫦', '👶', '🧒',
'👦', '👧', '🧑', '👱', '👨', '🧔', '👩', '🧓', '👴', '👵', '🙍', '🙎', '🙅', '🙆', '💁', '🙋', '🧏', '🙇',
'🤦', '🤷', '👮', '🕵️', '💂', '🥷', '👷', '🫅', '🤴', '👸', '👲', '🧕', '🤵', '👰', '🤰', '🫃', '🫄', '🤱',
'👼', '🎅', '🤶', '🧑‍🎄', '🦸', '🦹', '🧙', '🧝', '🧛', '🧟', '🧞', '🧜', '🧚', '🧑‍🤝‍🧑', '👫', '👬', '👭', '💏', '💑', '👪',
],
Animals: [
'🐶','🐱','🐭','🐹','🐰','🦊','🐻','🐼','🐻‍❄️','🐨','🐯','🦁','🐮','🐷','🐸','🐵','🙈','🙉',
'🙊','🐒','🦆','🦅','🦉','🦇','🐝','🪱','🐛','🦋','🐌','🐞','🐜','🪲','🦗','🪳','🕷️','🦂',
'🐢','🐍','🦎','🦖','🦕','🐙','🦑','🦐','🦞','🦀','🐡','🐠','🐟','🐬','🐳','🐋','🦈','🦭',
'🐊','🐅','🐆','🦓','🦍','🦧','🦣','🐘','🦛','🦏','🐪','🐫','🦒','🦘','🦬','🐃','🐂','🐄',
'🐎','🐖','🐏','🐑','🦙','🐐','🦌','🐕','🐩','🦮','🐕‍🦺','🐈','🐈‍⬛','🐓','🦃','🦤','🦚','🦜',
'🦢','🦩','🕊️','🐇','🦝','🦨','🦡','🦫','🦦','🦥','🐁','🐀','🐿️','🦔','🐾','🐉','🐲','🌵',
'🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼', '🐻‍❄️', '🐨', '🐯', '🦁', '🐮', '🐷', '🐸', '🐵', '🙈', '🙉',
'🙊', '🐒', '🦆', '🦅', '🦉', '🦇', '🐝', '🪱', '🐛', '🦋', '🐌', '🐞', '🐜', '🪲', '🦗', '🪳', '🕷️', '🦂',
'🐢', '🐍', '🦎', '🦖', '🦕', '🐙', '🦑', '🦐', '🦞', '🦀', '🐡', '🐠', '🐟', '🐬', '🐳', '🐋', '🦈', '🦭',
'🐊', '🐅', '🐆', '🦓', '🦍', '🦧', '🦣', '🐘', '🦛', '🦏', '🐪', '🐫', '🦒', '🦘', '🦬', '🐃', '🐂', '🐄',
'🐎', '🐖', '🐏', '🐑', '🦙', '🐐', '🦌', '🐕', '🐩', '🦮', '🐕‍🦺', '🐈', '🐈‍⬛', '🐓', '🦃', '🦤', '🦚', '🦜',
'🦢', '🦩', '🕊️', '🐇', '🦝', '🦨', '🦡', '🦫', '🦦', '🦥', '🐁', '🐀', '🐿️', '🦔', '🐾', '🐉', '🐲', '🌵',
],
Food: [
'🍎','🍊','🍋','🍌','🍍','🥭','🍓','🍒','🍑','🥝','🍅','🥥','🥑','🍆','🥔','🥕','🌽','🌶️',
'🫑','🥒','🥬','🥦','🧄','🧅','🍄','🥜','🌰','🍞','🥐','🥖','🫓','🥨','🧀','🥚','🍳','🧈',
'🥞','🧇','🥓','🥩','🍗','🍖','🦴','🌭','🍔','🍟','🍕','🫔','🌮','🌯','🥙','🧆','🥚','🍱',
'🍘','🍙','🍚','🍛','🍜','🍝','🍠','🍢','🍣','🍤','🍥','🥮','🍡','🥟','🥠','🥡','🦪','🍦',
'🍧','🍨','🍩','🍪','🎂','🍰','🧁','🥧','🍫','🍬','🍭','🍮','🍯','🍼','🥛','☕','🫖','🍵',
'🧃','🥤','🧋','🍶','🍺','🍻','🥂','🍷','🥃','🍸','🍹','🧉','🍾','🧊','🥄','🍴','🍽️','🥢',
'🍎', '🍊', '🍋', '🍌', '🍍', '🥭', '🍓', '🍒', '🍑', '🥝', '🍅', '🥥', '🥑', '🍆', '🥔', '🥕', '🌽', '🌶️',
'🫑', '🥒', '🥬', '🥦', '🧄', '🧅', '🍄', '🥜', '🌰', '🍞', '🥐', '🥖', '🫓', '🥨', '🧀', '🥚', '🍳', '🧈',
'🥞', '🧇', '🥓', '🥩', '🍗', '🍖', '🦴', '🌭', '🍔', '🍟', '🍕', '🫔', '🌮', '🌯', '🥙', '🧆', '🥚', '🍱',
'🍘', '🍙', '🍚', '🍛', '🍜', '🍝', '🍠', '🍢', '🍣', '🍤', '🍥', '🥮', '🍡', '🥟', '🥠', '🥡', '🦪', '🍦',
'🍧', '🍨', '🍩', '🍪', '🎂', '🍰', '🧁', '🥧', '🍫', '🍬', '🍭', '🍮', '🍯', '🍼', '🥛', '☕', '🫖', '🍵',
'🧃', '🥤', '🧋', '🍶', '🍺', '🍻', '🥂', '🍷', '🥃', '🍸', '🍹', '🧉', '🍾', '🧊', '🥄', '🍴', '🍽️', '🥢',
],
Travel: [
'🚗','🚕','🚙','🚌','🚎','🏎️','🚓','🚑','🚒','🚐','🛻','🚚','🚛','🚜','🦯','🦽','🦼','🛺',
'🚲','🛴','🛵','🏍️','🛺','🚨','🚔','🚍','🚘','🚖','🚡','🚠','🚟','🚃','🚋','🚞','🚝','🚄',
'🚅','🚈','🚂','🚆','🚇','🚊','🚉','✈️','🛫','🛬','🛩️','💺','🛸','🚁','🛶','⛵','🚤','🛥️',
'🛳️','⛴️','🚢','⚓','🗺️','🧭','🏔️','⛰️','🌋','🗻','🏕️','🏖️','🏜️','🏝️','🏞️','🏟️','🏛️','🏗️',
'🧱','🪨','🪵','🛖','🏘️','🏚️','🏠','🏡','🏢','🏣','🏤','🏥','🏦','🏨','🏩','🏪','🏫','🏬',
'🏭','🏯','🏰','💒','🗼','🗽','⛪','🕌','🛕','🕍','⛩️','🕋','⛲','⛺','🌁','🌃','🏙️','🌄',
'🚗', '🚕', '🚙', '🚌', '🚎', '🏎️', '🚓', '🚑', '🚒', '🚐', '🛻', '🚚', '🚛', '🚜', '🦯', '🦽', '🦼', '🛺',
'🚲', '🛴', '🛵', '🏍️', '🛺', '🚨', '🚔', '🚍', '🚘', '🚖', '🚡', '🚠', '🚟', '🚃', '🚋', '🚞', '🚝', '🚄',
'🚅', '🚈', '🚂', '🚆', '🚇', '🚊', '🚉', '✈️', '🛫', '🛬', '🛩️', '💺', '🛸', '🚁', '🛶', '⛵', '🚤', '🛥️',
'🛳️', '⛴️', '🚢', '⚓', '🗺️', '🧭', '🏔️', '⛰️', '🌋', '🗻', '🏕️', '🏖️', '🏜️', '🏝️', '🏞️', '🏟️', '🏛️', '🏗️',
'🧱', '🪨', '🪵', '🛖', '🏘️', '🏚️', '🏠', '🏡', '🏢', '🏣', '🏤', '🏥', '🏦', '🏨', '🏩', '🏪', '🏫', '🏬',
'🏭', '🏯', '🏰', '💒', '🗼', '🗽', '⛪', '🕌', '🛕', '🕍', '⛩️', '🕋', '⛲', '⛺', '🌁', '🌃', '🏙️', '🌄',
],
Activities: [
'⚽','🏀','🏈','⚾','🥎','🎾','🏐','🏉','🥏','🎱','🏓','🏸','🏒','🏑','🥍','🏏','🪃','🥅',
'⛳','🪁','🛝','🏹','🎣','🤿','🥊','🥋','🎽','🛹','🛷','⛸️','🥌','🎿','⛷️','🏂','🪂','🏋️',
'🤼','🤸','⛹️','🤺','🏇','🧘','🏄','🏊','🤽','🚣','🧗','🚵','🚴','🏆','🥇','🥈','🥉','🏅',
'🎖️','🏵️','🎗️','🎫','🎟️','🎪','🤹','🎭','🩰','🎨','🖼️','🎰','🎲','🧩','🪄','🎯','🪅','🎮',
'🕹️','🎳','🎻','🎷','🥁','🪘','🎺','🎸','🪗','🎹','🎵','🎶','🎼','🎤','🎧','📻','🎙️','🎚️',
'🎬','📽️','🎞️','📱','📲','☎️','📞','📟','📠','🔋','🪫','🔌','💡','🔦','🕯️','💸','💵','🪙',
'⚽', '🏀', '🏈', '⚾', '🥎', '🎾', '🏐', '🏉', '🥏', '🎱', '🏓', '🏸', '🏒', '🏑', '🥍', '🏏', '🪃', '🥅',
'⛳', '🪁', '🛝', '🏹', '🎣', '🤿', '🥊', '🥋', '🎽', '🛹', '🛷', '⛸️', '🥌', '🎿', '⛷️', '🏂', '🪂', '🏋️',
'🤼', '🤸', '⛹️', '🤺', '🏇', '🧘', '🏄', '🏊', '🤽', '🚣', '🧗', '🚵', '🚴', '🏆', '🥇', '🥈', '🥉', '🏅',
'🎖️', '🏵️', '🎗️', '🎫', '🎟️', '🎪', '🤹', '🎭', '🩰', '🎨', '🖼️', '🎰', '🎲', '🧩', '🪄', '🎯', '🪅', '🎮',
'🕹️', '🎳', '🎻', '🎷', '🥁', '🪘', '🎺', '🎸', '🪗', '🎹', '🎵', '🎶', '🎼', '🎤', '🎧', '📻', '🎙️', '🎚️',
'🎬', '📽️', '🎞️', '📱', '📲', '☎️', '📞', '📟', '📠', '🔋', '🪫', '🔌', '💡', '🔦', '🕯️', '💸', '💵', '🪙',
],
Objects: [
'⌚','📱','📲','💻','⌨️','🖥️','🖨️','🖱️','🖲️','💾','💿','📀','🧮','📷','📸','📹','🎥','📽️',
'📞','☎️','📟','📠','📺','📻','🧭','⏱️','⏲️','⏰','🕰️','⌛','⏳','📡','🔋','🪫','🔌','💡',
'🔦','🕯️','🪔','🧱','💰','💴','💵','💶','💷','💸','💳','🪙','💹','✉️','📧','📨','📩','📤',
'📥','📦','📫','📪','📬','📭','📮','🗳️','✏️','✒️','🖊️','🖋️','📝','📁','📂','🗂️','📅','📆',
'🗒️','🗓️','📇','📈','📉','📊','📋','📌','📍','🗺️','📏','📐','✂️','🗃️','🗄️','🗑️','🔒','🔓',
'🔏','🔐','🔑','🗝️','🔨','🪓','⛏️','⚒️','🛠️','🗡️','⚔️','🔫','🪃','🏹','🛡️','🪚','🔧','🪛',
'⌚', '📱', '📲', '💻', '⌨️', '🖥️', '🖨️', '🖱️', '🖲️', '💾', '💿', '📀', '🧮', '📷', '📸', '📹', '🎥', '📽️',
'📞', '☎️', '📟', '📠', '📺', '📻', '🧭', '⏱️', '⏲️', '⏰', '🕰️', '⌛', '⏳', '📡', '🔋', '🪫', '🔌', '💡',
'🔦', '🕯️', '🪔', '🧱', '💰', '💴', '💵', '💶', '💷', '💸', '💳', '🪙', '💹', '✉️', '📧', '📨', '📩', '📤',
'📥', '📦', '📫', '📪', '📬', '📭', '📮', '🗳️', '✏️', '✒️', '🖊️', '🖋️', '📝', '📁', '📂', '🗂️', '📅', '📆',
'🗒️', '🗓️', '📇', '📈', '📉', '📊', '📋', '📌', '📍', '🗺️', '📏', '📐', '✂️', '🗃️', '🗄️', '🗑️', '🔒', '🔓',
'🔏', '🔐', '🔑', '🗝️', '🔨', '🪓', '⛏️', '⚒️', '🛠️', '🗡️', '⚔️', '🔫', '🪃', '🏹', '🛡️', '🪚', '🔧', '🪛',
],
Symbols: [
'❤️','🧡','💛','💚','💙','💜','🖤','🤍','🤎','💔','❣️','💕','💞','💓','💗','💖','💘','💝',
'💟','☮️','✝️','☪️','🕉️','☸️','✡️','🔯','🕎','☯️','☦️','🛐','⛎','♈','♉','♊','♋','♌',
'♍','♎','♏','♐','♑','♒','♓','🆔','⚛️','🉑','☢️','☣️','📴','📳','🈶','🈚','🈸','🈺',
'🈷️','✴️','🆚','💮','🉐','㊙️','㊗️','🈴','🈵','🈹','🈲','🅰️','🅱️','🆎','🆑','🅾️','🆘',
'❌','⭕','🛑','⛔','📛','🚫','💯','💢','♨️','🚷','🚯','🚳','🚱','🔞','📵','🚭','❗','❕',
'❓','❔','‼️','⁉️','🔅','🔆','📶','🛜','📳','📴','🔱','📛','🔰','♻️','✅','🈯','💹','❎',
'🌐','💠','Ⓜ️','🌀','💤','🏧','🚾','♿','🅿️','🛗','🈳','🈹','🚰','🔤','🔡','🔠','🆖','🆗',
'🆙','🆒','🆕','🆓','🔟','📊','🔣','✔️','☑️','🔘','🔲','🔳','⬛','⬜','◼️','◻️','◾','◽',
'▪️','▫️','🔶','🔷','🔸','🔹','🔺','🔻','💠','🔘','🔲','🔳','🏁','🚩','🎌','🏴','🏳️','⭐',
'🌟','💫','✨','🌈','☀️','🌤️','⛅','🌥️','☁️','🌦️','🌧️','⛈️','🌩️','🌨️','❄️','☃️','⛄','🌬️',
'❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍', '🤎', '💔', '❣️', '💕', '💞', '💓', '💗', '💖', '💘', '💝',
'💟', '☮️', '✝️', '☪️', '🕉️', '☸️', '✡️', '🔯', '🕎', '☯️', '☦️', '🛐', '⛎', '♈', '♉', '♊', '♋', '♌',
'♍', '♎', '♏', '♐', '♑', '♒', '♓', '🆔', '⚛️', '🉑', '☢️', '☣️', '📴', '📳', '🈶', '🈚', '🈸', '🈺',
'🈷️', '✴️', '🆚', '💮', '🉐', '㊙️', '㊗️', '🈴', '🈵', '🈹', '🈲', '🅰️', '🅱️', '🆎', '🆑', '🅾️', '🆘',
'❌', '⭕', '🛑', '⛔', '📛', '🚫', '💯', '💢', '♨️', '🚷', '🚯', '🚳', '🚱', '🔞', '📵', '🚭', '❗', '❕',
'❓', '❔', '‼️', '⁉️', '🔅', '🔆', '📶', '🛜', '📳', '📴', '🔱', '📛', '🔰', '♻️', '✅', '🈯', '💹', '❎',
'🌐', '💠', 'Ⓜ️', '🌀', '💤', '🏧', '🚾', '♿', '🅿️', '🛗', '🈳', '🈹', '🚰', '🔤', '🔡', '🔠', '🆖', '🆗',
'🆙', '🆒', '🆕', '🆓', '🔟', '📊', '🔣', '✔️', '☑️', '🔘', '🔲', '🔳', '⬛', '⬜', '◼️', '◻️', '◾', '◽',
'▪️', '▫️', '🔶', '🔷', '🔸', '🔹', '🔺', '🔻', '💠', '🔘', '🔲', '🔳', '🏁', '🚩', '🎌', '🏴', '🏳️', '⭐',
'🌟', '💫', '✨', '🌈', '☀️', '🌤️', '⛅', '🌥️', '☁️', '🌦️', '🌧️', '⛈️', '🌩️', '🌨️', '❄️', '☃️', '⛄', '🌬️',
],
};
@ -115,14 +115,14 @@ const EmojiPicker = () => ({
onclick: () => { ChatHubState.emojiSearch = ''; },
}, m('i.fas.fa-times')),
]),
!search && m('.emoji-categories', EMOJI_CATEGORIES.map(c =>
!search && m('.emoji-categories', EMOJI_CATEGORIES.map((c) =>
m('button.emoji-cat-btn' + (c === cat ? '.active' : ''), {
title: c,
onclick: () => { ChatHubState.emojiCategory = c; },
}, EMOJI_ICONS[c])
)),
m('.emoji-grid',
emojis.map(e =>
emojis.map((e) =>
m('button.emoji-btn', {
onclick: () => {
insertEmojiIntoTextarea(e, onSelect);

View File

@ -1,7 +1,5 @@
const m = require('mithril');
const rs = require('rswebui');
const peopleUtil = require('people/people_util');
const people = require('people/people');
// **************** utility functions ********************
@ -35,7 +33,7 @@ function loadDistantChatDetails(pid, apply) {
rs.rsJsonApiRequest(
'/rsChats/getDistantChatStatus',
{
pid: pid,
pid,
},
(detail, success) => {
if (success && detail.retval) {
@ -118,7 +116,7 @@ function renderChatMessage(rawText) {
if (src) {
parts.push(
m('img.chat-embedded-image', {
src: src,
src,
style: {
maxWidth: '100%',
maxHeight: '300px',
@ -160,7 +158,7 @@ function renderChatMessage(rawText) {
if (rawText.trim().startsWith('data:image/')) {
const src = rawText.trim();
return m('img.chat-embedded-image', {
src: src,
src,
style: {
maxWidth: '100%',
maxHeight: '300px',
@ -248,7 +246,7 @@ function renderTextWithEmoji(text) {
const parts = [];
let last = 0;
let match;
// eslint-disable-next-line no-cond-assign
while ((match = emojiRegex.exec(text)) !== null) {
if (match[0].length === 0) { emojiRegex.lastIndex++; continue; }
if (match.index > last) parts.push(text.slice(last, match.index));
@ -442,8 +440,8 @@ const Message = () => {
x: e.clientX,
y: e.clientY,
messageText: targetText,
username: username,
gxsId: gxsId,
username,
gxsId,
};
m.redraw();
};
@ -581,7 +579,7 @@ const ChatLobbyModel = {
loadHistory(id, type) {
const chatPeerId = {
broadcast_status_peer_id: '00000000000000000000000000000000',
type: type,
type,
peer_id: '00000000000000000000000000000000',
distant_chat_id: '00000000000000000000000000000000',
lobby_id: { xstr64: '0' },
@ -594,7 +592,7 @@ const ChatLobbyModel = {
rs.rsJsonApiRequest(
'/rsHistory/getMessages',
{
chatPeerId: chatPeerId,
chatPeerId,
loadCount: 20,
},
(data, success) => {
@ -623,11 +621,11 @@ const ChatLobbyModel = {
rs.rsJsonApiRequest(
'/rsHistory/getMessages',
{
chatPeerId: chatPeerId,
chatPeerId,
loadCount: 0,
},
(data, success) => {
let msgs = (success && data && data.msgs) ? data.msgs : [];
const msgs = (success && data && data.msgs) ? data.msgs : [];
msgs.sort((a, b) => (a.sendTime || a.recvTime) - (b.sendTime || b.recvTime));
ChatHubState.fullHistoryMessages = msgs;
ChatHubState.isHistoryLoading = false;
@ -642,7 +640,7 @@ const ChatLobbyModel = {
'/rsChats/setIdentityForChatLobby',
{
lobby_id: { xstr64: lobbyId },
nick: nick,
nick,
},
() => m.route.set('/chat/:lobby', { lobby: lobbyId }),
true
@ -685,7 +683,7 @@ const ChatLobbyModel = {
const id = this.lastLobbyId || m.route.param('lobby');
const cid = {
broadcast_status_peer_id: '00000000000000000000000000000000',
type: type,
type,
peer_id: '00000000000000000000000000000000',
distant_chat_id: '00000000000000000000000000000000',
lobby_id: { xstr64: '0' },
@ -805,13 +803,13 @@ const ChatLobbyModel = {
'/rsChats/sendChat',
{
id: cid,
msg: msg,
msg,
},
(data, success) => {
if (success) {
const echoMsg = {
chat_id: cid,
msg: msg,
msg,
sendTime: Math.floor(Date.now() / 1000),
lobby_peer_gxs_id: this.currentLobby.gxs_id,
};

View File

@ -10,8 +10,8 @@ const ConfigChat = () => {
let maxStorageDays = 10;
// History states
let historyEnable = { private: true, distant: true, lobby: true };
let historySaveCount = { private: 500, distant: 500, lobby: 500 };
const historyEnable = { private: true, distant: true, lobby: true };
const historySaveCount = { private: 500, distant: 500, lobby: 500 };
function loadSettings() {
// Load Own Identities

View File

@ -579,8 +579,8 @@ const displayHiddenServiceInfo = () => {
details && details.hiddenNodeAddress &&
m('.hidden-service-info', { style: 'display: flex; flex-direction: column; gap: 0.75rem; width: 100%;' }, [
m('p.proxy-description', { style: 'margin-bottom: 0.5rem; color: #475569;' }, details.hiddenType === 4
? "I2P has been automatically configured by Retroshare. You shouldn't need to change anything here."
: "Tor has been automatically configured by Retroshare. You shouldn't need to change anything here."
? 'I2P has been automatically configured by Retroshare. You shouldn\'t need to change anything here.'
: 'Tor has been automatically configured by Retroshare. You shouldn\'t need to change anything here.'
),
// Local Address + Local Port row
m('.nw-config-row', { style: 'display: grid; grid-template-columns: 200px 1fr; gap: 1rem; align-items: center;' }, [

View File

@ -2,7 +2,7 @@ const m = require('mithril');
const rs = require('rswebui');
const util = require('forums/forums_util');
const peopleUtil = require('people/people_util');
const { updatedisplayforums, loadPostContent, getTimestampValue, formatTimestamp } = require('./forums_util');
const { loadPostContent, getTimestampValue, formatTimestamp } = require('./forums_util');
function createforum() {
let title;
@ -75,75 +75,6 @@ function createforum() {
]),
};
}
const EditThread = () => {
let title = '';
let body = '';
return {
oninit: (vnode) => {
title = vnode.attrs.current_title;
body = vnode.attrs.current_body;
},
view: (vnode) =>
m('.widget', [
m('h3', 'Edit Thread'),
m('hr'),
m(
'iddisplay',
{
style: { display: 'block ruby' }, // same line block ruby
},
[
'Identity: ',
m('h5[id=authid]', rs.userList.username(vnode.attrs.authorId)),
]
),
m(
'titledisplay',
{
style: { display: 'block ruby' },
},
[
'Title: ',
m('input[type=text][placeholder=Title]', {
value: vnode.attrs.current_title,
oninput: (e) => (title = e.target.value),
}),
]
),
m('textarea[rows=5]', {
style: { width: '90%', display: 'block' },
oninput: (e) => (body = e.target.value),
value: vnode.attrs.current_body,
}),
m(
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsgxsforums/createPost', {
forumId: vnode.attrs.forumId,
mBody: body,
title,
authorId: vnode.attrs.authorId,
parentId: vnode.attrs.current_parent,
origPostId: vnode.attrs.current_msgid,
});
res.body.retval === false
? util.popupmessage([m('h3', 'Error'), m('hr'), m('p', res.body.errorMessage)])
: util.popupmessage([
m('h3', 'Success'),
m('hr'),
m('p', 'Thread edited successfully'),
]);
util.updatedisplayforums(vnode.attrs.forumId);
m.redraw();
},
},
'Add'
),
]),
};
};
const AddThread = () => {
let title = '';
let body = '';
@ -228,166 +159,6 @@ const AddThread = () => {
// getTimestampValue and formatTimestamp are imported from forums_util.js
function displaythread() {
// recursive function to display all the threads
let groupmessagepair;
let unread;
let editpermission = false;
return {
view: (v) => {
const thread = v.attrs.threadStruct.thread;
groupmessagepair = { first: thread.mMeta.mGroupId, second: thread.mMeta.mOrigMsgId };
let parMap = [];
if (util.Data.ParentThreadMap[thread.mMeta.mOrigMsgId]) {
parMap = util.Data.ParentThreadMap[thread.mMeta.mOrigMsgId];
}
unread = thread.mMeta.mMsgStatus === util.THREAD_UNREAD;
v.attrs.identity &&
v.attrs.identity.map((val) => {
if (val.localeCompare(thread.mMeta.mAuthorId) === 0) {
// if the author of the thread matches one of our own ids
editpermission = true;
}
});
return [
m(
'tr',
{
style: unread ? { fontWeight: 'bold' } : '',
},
[
Object.keys(parMap).length // if this thread has some replies
? m(
'td',
m('i.fas.fa-angle-right', {
class: 'fa-rotate-' + (v.attrs.threadStruct.showReplies ? '90' : '0'),
style: 'margin-top:12px',
onclick: () => {
v.attrs.threadStruct.showReplies = !v.attrs.threadStruct.showReplies;
},
})
)
: m('td', ''),
m(
'td',
{
style: {
position: 'relative',
'--replyDepth': v.attrs.replyDepth,
left: 'calc(30px*var(--replyDepth))', // shifts reply by 30 px
padding: '10px 0',
},
},
[
m('div.date', { style: { fontSize: '0.8em', color: '#888' } },
formatTimestamp(thread.mMeta.mPublishTs)
),
m('div.title', {
style: { fontWeight: 'bold', fontSize: '1.1em', cursor: 'pointer', margin: '5px 0' },
onclick: async () => {
v.attrs.changeThread(thread.mMeta.mOrigMsgId);
if (unread) {
const res = await rs.rsJsonApiRequest('/rsgxsforums/markRead', {
messageId: groupmessagepair,
read: true,
});
if (res.body.retval) {
updatedisplayforums(thread.mMeta.mGroupId);
m.redraw();
}
}
},
ondblclick: () =>
(v.attrs.threadStruct.showReplies = !v.attrs.threadStruct.showReplies),
}, [
thread.mMeta.mMsgName,
m('options', { style: 'display:block; margin-top: 5px;' }, [
m(
'button',
{
style: 'font-size:12px; margin-right: 5px;',
onclick: (e) => {
e.stopPropagation();
util.popupmessage(
m(AddThread, {
parent_thread: thread.mMeta.mMsgName,
forumId: thread.mMeta.mGroupId,
authorId: v.attrs.identity,
parentId: thread.mMeta.mMsgId,
})
);
},
},
'Reply'
),
editpermission &&
m(
'button',
{
style: 'font-size:12px; margin-right: 5px;',
onclick: async (e) => {
e.stopPropagation();
const body = await loadPostContent(
thread.mMeta.mGroupId,
thread.mMeta.mOrigMsgId
);
util.popupmessage(
m(EditThread, {
current_thread: thread.mMeta.mMsgName,
forumId: thread.mMeta.mGroupId,
current_title: thread.mMeta.mMsgName,
current_body: body || '',
authorId: thread.mMeta.mAuthorId,
current_parent: thread.mMeta.mParentId,
current_msgid: thread.mMeta.mOrigMsgId,
})
);
},
},
'Edit'
),
m(
'button',
{
style: { fontSize: '12px' },
onclick: async (e) => {
e.stopPropagation();
const res = await rs.rsJsonApiRequest('/rsgxsforums/markRead', {
messageId: groupmessagepair,
read: !unread ? true : false,
});
if (res.body.retval) {
updatedisplayforums(thread.mMeta.mGroupId);
m.redraw();
}
},
},
unread ? 'Mark Read' : 'Mark Unread'
),
]),
]),
m('div.author', { style: { fontSize: '0.9em', fontStyle: 'italic' } }, rs.userList.username(thread.mMeta.mAuthorId)),
]
),
]
),
v.attrs.threadStruct.showReplies &&
Object.keys(parMap).map((key, index) =>
m(displaythread, {
// recursive call to all replies
threadStruct: util.Data.Threads[parMap[key].mGroupId][parMap[key].mOrigMsgId],
replyDepth: v.attrs.replyDepth + 1,
identity: v.attrs.identity,
changeThread: v.attrs.changeThread,
})
),
];
},
};
}
const ThreadView = () => {
let ownId;
return {
@ -449,7 +220,7 @@ const ThreadView = () => {
style: { marginRight: '10px' },
onclick: () => util.popupmessage(m(AddThread, {
parent_thread: meta.mMsgName,
forumId: forumId,
forumId,
authorId: ownId,
parentId: msgId,
}))

View File

@ -106,7 +106,7 @@ async function updatedisplayforums(keyid) {
const threadStruct = {
thread: { mMeta: meta, mMsg: null },
replies: replies,
replies,
showReplies: false,
};
@ -156,7 +156,7 @@ async function loadPostContent(forumId, msgId) {
try {
const res = await rs.rsJsonApiRequest('/rsgxsforums/getForumContent', {
forumId: forumId,
forumId,
msgsIds: [msgId],
});
if (res && res.body && res.body.retval && res.body.msgs && res.body.msgs.length > 0) {

View File

@ -41,7 +41,7 @@ function renderPolygon(shapePoints, x, y, angle, shapeAngle, size, color) {
function toSvg(hash, width) {
if (!hash || hash.length < 18) {
hash = "00000000000000000000000000000000";
hash = '00000000000000000000000000000000';
}
const csh = parseInt(hash.substr(0, 1), 16);
@ -99,4 +99,4 @@ function toSvg(hash, width) {
module.exports = {
toSvg
};
};

View File

@ -18,7 +18,7 @@ function formatFileSize(bytes) {
const Layout = () => {
let showCc = false;
let showBcc = false;
let ownAvatars = {};
const ownAvatars = {};
let attachments = [];
let showEmojiPicker = false;
let emojiSearch = '';
@ -397,7 +397,7 @@ const Layout = () => {
const attHtml = `
<br/><hr style="border:none;border-top:1px solid #e2e8f0;margin:1rem 0;"/><div style="margin-top:10px;font-weight:bold;color:#475569;font-size:0.9rem;">Attachments (${attachments.length}):</div>
<ul style="list-style:none;padding:0;margin:6px 0;">
${attachments.map(att => `<li style="padding:4px 0;color:#1e293b;font-size:0.875rem;">📎 <b>${att.name}</b> <span style="color:#94a3b8;font-size:0.8em;">(${att.size})</span></li>`).join('')}
${attachments.map((att) => `<li style="padding:4px 0;color:#1e293b;font-size:0.875rem;">📎 <b>${att.name}</b> <span style="color:#94a3b8;font-size:0.8em;">(${att.size})</span></li>`).join('')}
</ul>
`;
fullMailBody += attHtml;
@ -701,7 +701,7 @@ const Layout = () => {
}),
]),
!emojiSearch && m('.emoji-cat-bar', { style: 'display: flex; background: #f8fafc; border-bottom: 1px solid #e2e8f0; padding: 0.25rem; overflow-x: auto;' },
chatEmoji.EMOJI_CATEGORIES.map(c =>
chatEmoji.EMOJI_CATEGORIES.map((c) =>
m('button', {
style: `border: none; background: ${c === emojiCategory ? '#ffffff' : 'transparent'}; border-radius: 0.25rem; padding: 0.3rem 0.4rem; cursor: pointer; font-size: 1rem; box-shadow: ${c === emojiCategory ? '0 1px 2px rgba(0,0,0,0.1)' : 'none'};`,
title: c,
@ -711,9 +711,9 @@ const Layout = () => {
),
m('.emoji-grid-body', { style: 'padding: 0.5rem; display: grid; grid-template-columns: repeat(7, 1fr); gap: 0.25rem; max-height: 230px; overflow-y: auto;' },
(emojiSearch
? Object.values(chatEmoji.EMOJI_DATA).flat().filter(e => e.includes(emojiSearch))
? Object.values(chatEmoji.EMOJI_DATA).flat().filter((e) => e.includes(emojiSearch))
: (chatEmoji.EMOJI_DATA[emojiCategory] || [])
).map(e =>
).map((e) =>
m('button', {
style: 'border: none; background: transparent; font-size: 1.25rem; cursor: pointer; padding: 0.25rem; border-radius: 0.25rem; transition: background 0.15s ease;',
onmouseenter: (ev) => (ev.currentTarget.style.background = '#f1f5f9'),

View File

@ -195,7 +195,7 @@ const GenericMailList = () => {
m(util.MessageSummary, {
key: msg.msgId,
details: msg,
category: category,
category,
})
)
)

View File

@ -622,11 +622,11 @@ const Table = () => {
};
let totalItems = 0;
let tbody = v.children[0];
const tbody = v.children[0];
if (tbody && tbody.children) {
const flatChildren = Array.isArray(tbody.children) ? tbody.children.flat().filter(Boolean) : [tbody.children].filter(Boolean);
totalItems = flatChildren.length;
const start = currentPage * pageSize;
const end = start + pageSize;
tbody.children = flatChildren.slice(start, end);

View File

@ -149,7 +149,7 @@ function sendDirectChatMessage() {
'/rsChats/sendChat',
{
id: { type: 1, peer_id: State.currentChatPeerId },
msg: msg,
msg,
},
(data, success) => {
if (success) {

View File

@ -100,14 +100,6 @@ const ChatTab = () => {
const canTalk = State.distantChatStatus && State.distantChatStatus.status === 2;
// Filter history by search query for history modal
const query = (State.historySearchQuery || '').toLowerCase();
const filteredHistory = (State.fullHistoryMessages || []).filter((msg) => {
if (!query) return true;
const text = (msg.msg || msg.message || '').toLowerCase();
return text.includes(query);
});
return m('.network-chat-view', [
m('.chat-identity-select-container', {
style: 'padding: 0.5rem 1rem; background-color: #ffffff; border-bottom: 1px solid #cbd5e1; display: flex; align-items: center; justify-content: space-between; font-size: 0.85rem;',

View File

@ -33,7 +33,7 @@ const PeopleSidebar = () => {
},
view: () => {
// 1. Determine list based on mainTab ('people' vs 'chats')
let displayItems = [];
let displayItems;
// 0. Compute active chats count (conversations with real message history)
const allUserGroupIds = new Set((rs.userList.users || []).map((u) => u.mGroupId));
@ -47,7 +47,7 @@ const PeopleSidebar = () => {
});
if (State.mainTab === 'people') {
let baseList = [];
let baseList;
if (State.activeFilter === 'own') {
baseList = peopleUtil.sortIds(State.ownGxsIds) || [];
} else if (State.activeFilter === 'contacts') {
@ -57,13 +57,13 @@ const PeopleSidebar = () => {
}
displayItems = baseList.filter((item) => {
let name = State.activeFilter === 'own' ? (rs.userList.username(item) || 'Unknown') : (item.mGroupName || 'Unknown');
const name = State.activeFilter === 'own' ? (rs.userList.username(item) || 'Unknown') : (item.mGroupName || 'Unknown');
return name.toLowerCase().includes(State.searchString.toLowerCase());
});
displayItems.sort((a, b) => {
let nameA = State.activeFilter === 'own' ? (rs.userList.username(a) || '') : (a.mGroupName || '');
let nameB = State.activeFilter === 'own' ? (rs.userList.username(b) || '') : (b.mGroupName || '');
const nameA = State.activeFilter === 'own' ? (rs.userList.username(a) || '') : (a.mGroupName || '');
const nameB = State.activeFilter === 'own' ? (rs.userList.username(b) || '') : (b.mGroupName || '');
return nameA.localeCompare(nameB);
});
} else {

View File

@ -359,7 +359,7 @@ function loadChatMessages() {
rs.rsJsonApiRequest(
'/rsHistory/getMessages',
{
chatPeerId: chatPeerId,
chatPeerId,
loadCount: 50,
},
(data, success) => {
@ -509,7 +509,7 @@ function preloadAllChatHistory() {
if (!existing || lastTime > existing.lastTime) {
State.chatHistoryMap[gxsId] = {
lastMsg: last.message || last.msg || '',
lastTime: lastTime,
lastTime,
};
m.redraw();
}
@ -573,7 +573,7 @@ function loadAllHistoryForSelectedPeer(callback) {
rs.rsJsonApiRequest(
'/rsHistory/getMessages',
{
chatPeerId: chatPeerId,
chatPeerId,
loadCount: 0, // 0 = load all messages in C++
},
(msgData, success) => {
@ -588,7 +588,7 @@ function loadAllHistoryForSelectedPeer(callback) {
const key = `${mItem.sendTime || mItem.recvTime}_${text}`;
if (!map.has(key)) map.set(key, mItem);
});
let uniqueMsgs = Array.from(map.values());
const uniqueMsgs = Array.from(map.values());
uniqueMsgs.sort((a, b) => (a.sendTime || a.recvTime) - (b.sendTime || b.recvTime));
State.fullHistoryMessages = uniqueMsgs;
State.isHistoryLoading = false;

View File

@ -70,7 +70,7 @@ const UserAvatar = () => ({
width: sizeStr,
height: sizeStr,
borderRadius: isSquare ? '0' : '50%',
backgroundColor: backgroundColor,
backgroundColor,
}
},
m('p', {

View File

@ -0,0 +1,51 @@
import js from '@eslint/js';
import globals from 'globals';
export default [
{
ignores: ['app/mithril.js', 'assets/**', 'make-src/**'],
},
{
files: ['app/**/*.js'],
languageOptions: {
ecmaVersion: 2020,
sourceType: 'commonjs',
globals: {
...globals.browser,
...globals.commonjs,
},
},
rules: {
...js.configs.recommended.rules,
'linebreak-style': ['off', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'arrow-spacing': ['error', { before: true, after: true }],
'arrow-parens': ['error', 'always'],
'comma-style': ['error', 'last'],
'comma-spacing': ['error', { before: false, after: true }],
camelcase: ['error', {
allow: ['^UNSAFE_'],
properties: 'never',
ignoreGlobals: true,
}],
'eol-last': 'error',
eqeqeq: ['error', 'always', { null: 'ignore' }],
'no-irregular-whitespace': 'error',
'no-trailing-spaces': 'error',
'no-unexpected-multiline': 'error',
'no-unreachable': 'error',
'no-var': 'warn',
'no-unused-vars': ['error', {
args: 'none',
caughtErrors: 'none',
ignoreRestSiblings: true,
vars: 'all',
}],
'object-shorthand': 'error',
'prefer-const': ['error', { destructuring: 'all' }],
'semi-style': ['warn', 'last'],
'spaced-comment': ['warn', 'always'],
},
},
];

View File

@ -8,7 +8,7 @@ echo "### Starting WebUI build ###"
set src=%~dp0..\..\webui-src
rem Output destination
if "%~1" == "" (
if "%~1"=="" (
set publicdest=%~dp0..\..\webui
) else (
set publicdest=%~1\webui
@ -36,6 +36,7 @@ copy %src%\make-src\template.js %publicdest%\app.js
pushd %src%\app
set "basefolder=%cd%\"
set "lastsection="
for /R %%F in (*.js) do call :addfile-js "%basefolder%" "%%F"
popd
@ -54,7 +55,15 @@ set registername=%~dpn2
set registername=!registername:%basefolder%=!
set registername=%registername:\=/%
echo - adding %registername% ...
for /f "tokens=1,2 delims=/" %%A in ("!registername!") do (
if "%%B"=="" (
echo - adding !registername! ...
set "lastsection="
) else if not "!lastsection!"=="%%A" (
echo - adding %%A/* ...
set "lastsection=%%A"
)
)
echo require.register("%registername%", function(exports, require, module) { >> %publicdest%\app.js
type %fname% >> %publicdest%\app.js
echo. >> %publicdest%\app.js

View File

@ -1,68 +1,85 @@
#!/bin/bash
#!/bin/sh
# create webfiles from sources at compile time (works without npm/node.js)
# Create webfiles from sources at compile time (works without npm/node.js)
#
# Usage: build.sh [DEST_PARENT] [TARGET_FILE] [EXTRA_COPY_DIR]
# DEST_PARENT parent dir of the generated webui/ (default: repo root)
# TARGET_FILE build only this file (index.html|styles.css|app.js); default: all
# EXTRA_COPY_DIR also copy TARGET_FILE into EXTRA_COPY_DIR/webui/
set -eu
echo "### Starting WebUI build ###"
src=$(readlink -f $(dirname $0))/../../webui-src
# Resolve the script's own directory portably.
script_dir=$(cd -- "$(dirname -- "$0")" && pwd -P)
src="$script_dir/../../webui-src"
if [ "$1" = "" ]; then
publicdest=$(readlink -f $(dirname $0))/../../webui
dest_parent="${1:-}"
target="${2:-}"
extra_copy_dir="${3:-}"
if [ -z "$dest_parent" ]; then
publicdest="$script_dir/../../webui"
else
publicdest=$1/webui
publicdest="$dest_parent/webui"
fi
if [ "$2" = "" ]; then
if [ -d "$publicdest" ]; then
echo removing existing $publicdest
rm $publicdest -R
fi
# Full rebuild (no specific target): remove any existing output first.
if [ -z "$target" ] && [ -d "$publicdest" ]; then
echo "removing existing $publicdest"
rm -rf -- "$publicdest"
fi
if [ ! -d "$publicdest" ]; then
echo creating $publicdest
mkdir $publicdest
mkdir -p -- "$publicdest"
if [ -z "$target" ] || [ "$target" = "index.html" ]; then
echo "copying html file"
cp -- "$src/index.html" "$publicdest/"
fi
# For using recursive directory search(requires bash v4+)
shopt -s globstar
if [ "$2" = "" ]||[ "$2" = "index.html" ]; then
echo copying html file
cp $src/index.html $publicdest/
if [ -z "$target" ] || [ "$target" = "styles.css" ]; then
echo "copying css file"
cp -- "$src/styles.css" "$publicdest/"
fi
if [ "$2" = "" ]||[ "$2" = "styles.css" ]; then
echo copying css file
cp $src/styles.css $publicdest/
if [ -z "$target" ] || [ "$target" = "app.js" ]; then
echo "building app.js:"
echo "- copying template.js ..."
cp -- "$src/make-src/template.js" "$publicdest/app.js"
js_root="$src/app"
find "$js_root" -type f -name '*.js' | LC_ALL=C sort | while IFS= read -r filename; do
fname="${filename#"$js_root/"}"
fname="${fname%.*}"
case "$fname" in
*/*)
section="${fname%%/*}/*"
if [ "$section" != "${last_section:-}" ]; then
echo "- adding $section ..."
last_section="$section"
fi
;;
*)
echo "- adding $fname ..."
last_section=
;;
esac
{
printf 'require.register("%s", function(exports, require, module) {\n' "$fname"
cat -- "$filename"
printf '\n});\n'
} >>"$publicdest/app.js"
done
fi
if [ "$2" = "" ]||[ "$2" = "app.js" ]; then
echo building app.js:
echo - copying template.js ...
cp $src/make-src/template.js $publicdest/app.js
echo "copying assets folder"
cp -R -- "$src/assets/." "$publicdest/"
js_source=$src/app/
for filename in $src/app/**/*.js; do
fname="${filename#$js_source}"
fname="${fname%.*}"
echo - adding $fname ...
echo require.register\(\"$fname\", function\(exports, require, module\) { >> $publicdest/app.js
cat $filename >> $publicdest/app.js
echo >> $publicdest/app.js
echo }\)\; >> $publicdest/app.js
done
if [ -n "$target" ] && [ -n "$extra_copy_dir" ]; then
mkdir -p -- "$extra_copy_dir/webui"
echo "copying $target to $extra_copy_dir/webui/$target"
cp -- "$publicdest/$target" "$extra_copy_dir/webui/$target"
fi
echo copying assets folder
cp -r $src/assets/* $publicdest/
if [ "$2" != "" ]&&[ "$3" != "" ]; then
if [ ! -d "$3/webui" ]; then
echo creating $3/webui
mkdir $3/webui
fi
echo copying $2 nach $3/webui/$2
cp $publicdest/$2 $3/webui/$2
fi
echo "### WebUI build complete ###"

1311
webui-src/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,10 +4,17 @@
"description": "Retroshare's Web Interface",
"scripts": {
"watch": "rm ./styles.css && sass --watch --embed-sources --embed-source-map ./app/scss/main.scss ./styles.css",
"build": "sass --no-source-map --style=compressed ./app/scss/main.scss ./styles.css"
"build": "sass --no-source-map --style=compressed ./app/scss/main.scss ./styles.css && sh ./make-src/build.sh",
"lint": "eslint app && node --check ../webui/app.js && sh -n make-src/build.sh && echo 'Lint checks passed.'"
},
"license": "ISC",
"engines": {
"node": ">=24"
},
"devDependencies": {
"sass": "^1.60.0"
"@eslint/js": "^10.0.1",
"eslint": "^10.8.0",
"globals": "^17.8.0",
"sass": "1.97.3"
}
}

View File

@ -1,240 +0,0 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
devDependencies:
sass:
specifier: ^1.60.0
version: 1.97.3
packages:
'@parcel/watcher-android-arm64@2.5.6':
resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [android]
'@parcel/watcher-darwin-arm64@2.5.6':
resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [darwin]
'@parcel/watcher-darwin-x64@2.5.6':
resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [darwin]
'@parcel/watcher-freebsd-x64@2.5.6':
resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [freebsd]
'@parcel/watcher-linux-arm-glibc@2.5.6':
resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
libc: [glibc]
'@parcel/watcher-linux-arm-musl@2.5.6':
resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
libc: [musl]
'@parcel/watcher-linux-arm64-glibc@2.5.6':
resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@parcel/watcher-linux-arm64-musl@2.5.6':
resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@parcel/watcher-linux-x64-glibc@2.5.6':
resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@parcel/watcher-linux-x64-musl@2.5.6':
resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
'@parcel/watcher-win32-arm64@2.5.6':
resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [win32]
'@parcel/watcher-win32-ia32@2.5.6':
resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==}
engines: {node: '>= 10.0.0'}
cpu: [ia32]
os: [win32]
'@parcel/watcher-win32-x64@2.5.6':
resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [win32]
'@parcel/watcher@2.5.6':
resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==}
engines: {node: '>= 10.0.0'}
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
immutable@5.1.5:
resolution: {integrity: sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==}
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
picomatch@4.0.3:
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
engines: {node: '>=12'}
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
sass@1.97.3:
resolution: {integrity: sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==}
engines: {node: '>=14.0.0'}
hasBin: true
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
snapshots:
'@parcel/watcher-android-arm64@2.5.6':
optional: true
'@parcel/watcher-darwin-arm64@2.5.6':
optional: true
'@parcel/watcher-darwin-x64@2.5.6':
optional: true
'@parcel/watcher-freebsd-x64@2.5.6':
optional: true
'@parcel/watcher-linux-arm-glibc@2.5.6':
optional: true
'@parcel/watcher-linux-arm-musl@2.5.6':
optional: true
'@parcel/watcher-linux-arm64-glibc@2.5.6':
optional: true
'@parcel/watcher-linux-arm64-musl@2.5.6':
optional: true
'@parcel/watcher-linux-x64-glibc@2.5.6':
optional: true
'@parcel/watcher-linux-x64-musl@2.5.6':
optional: true
'@parcel/watcher-win32-arm64@2.5.6':
optional: true
'@parcel/watcher-win32-ia32@2.5.6':
optional: true
'@parcel/watcher-win32-x64@2.5.6':
optional: true
'@parcel/watcher@2.5.6':
dependencies:
detect-libc: 2.1.2
is-glob: 4.0.3
node-addon-api: 7.1.1
picomatch: 4.0.3
optionalDependencies:
'@parcel/watcher-android-arm64': 2.5.6
'@parcel/watcher-darwin-arm64': 2.5.6
'@parcel/watcher-darwin-x64': 2.5.6
'@parcel/watcher-freebsd-x64': 2.5.6
'@parcel/watcher-linux-arm-glibc': 2.5.6
'@parcel/watcher-linux-arm-musl': 2.5.6
'@parcel/watcher-linux-arm64-glibc': 2.5.6
'@parcel/watcher-linux-arm64-musl': 2.5.6
'@parcel/watcher-linux-x64-glibc': 2.5.6
'@parcel/watcher-linux-x64-musl': 2.5.6
'@parcel/watcher-win32-arm64': 2.5.6
'@parcel/watcher-win32-ia32': 2.5.6
'@parcel/watcher-win32-x64': 2.5.6
optional: true
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
detect-libc@2.1.2:
optional: true
immutable@5.1.5: {}
is-extglob@2.1.1:
optional: true
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
optional: true
node-addon-api@7.1.1:
optional: true
picomatch@4.0.3:
optional: true
readdirp@4.1.2: {}
sass@1.97.3:
dependencies:
chokidar: 4.0.3
immutable: 5.1.5
source-map-js: 1.2.1
optionalDependencies:
'@parcel/watcher': 2.5.6
source-map-js@1.2.1: {}

View File

@ -72,7 +72,7 @@ win32-g++ {
} else {
# create dummy files, we need it to include files on first try
system(bash webui-src/make-src/build.sh .)
system(sh webui-src/make-src/build.sh .)
WEBUI_SRC_SCRIPT = webui-src/make-src/build.sh
@ -80,19 +80,19 @@ win32-g++ {
create_webfiles_html.output = webui/index.html
create_webfiles_html.input = WEBUI_SRC_HTML
create_webfiles_html.commands = bash $$_PRO_FILE_PWD_/webui-src/make-src/build.sh $$_PRO_FILE_PWD_ index.html .
create_webfiles_html.commands = sh $$_PRO_FILE_PWD_/webui-src/make-src/build.sh $$_PRO_FILE_PWD_ index.html .
create_webfiles_html.variable_out = JUNK
create_webfiles_html.CONFIG = combine no_link
create_webfiles_js.output = webui/app.js
create_webfiles_js.input = WEBUI_SRC_JS
create_webfiles_js.commands = bash $$_PRO_FILE_PWD_/webui-src/make-src/build.sh $$_PRO_FILE_PWD_ app.js .
create_webfiles_js.commands = sh $$_PRO_FILE_PWD_/webui-src/make-src/build.sh $$_PRO_FILE_PWD_ app.js .
create_webfiles_js.variable_out = JUNK
create_webfiles_js.CONFIG = combine no_link
create_webfiles_css.output = webui/styles.css
create_webfiles_css.input = WEBUI_SRC_CSS
create_webfiles_css.commands = bash $$_PRO_FILE_PWD_/webui-src/make-src/build.sh $$_PRO_FILE_PWD_ styles.css .
create_webfiles_css.commands = sh $$_PRO_FILE_PWD_/webui-src/make-src/build.sh $$_PRO_FILE_PWD_ styles.css .
create_webfiles_css.variable_out = JUNK
create_webfiles_css.CONFIG = combine no_link