Merge pull request #77 from zelfroster/fix-ui

Fix UI
This commit is contained in:
csoler 2023-07-03 15:36:06 +02:00 committed by GitHub
commit 806d13efca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 2235 additions and 2754 deletions

View File

@ -2,10 +2,9 @@ const m = require('mithril');
const rs = require('rswebui');
const util = require('boards/boards_util');
const Data = util.Data;
const peopleUtil = require('people/people_util');
const messageGroups = ['Public', 'Restricted Circle', 'Restricted Node Group'];
const messageGroupsCode = [util.PUBLIC, util.EXTERNAL, util.NODES_GROUP]; //rsgxscirles.h:50
const messageGroupsCode = [util.PUBLIC, util.EXTERNAL, util.NODES_GROUP]; // rsgxscirles.h:50
function createboard() {
let title;
@ -156,7 +155,6 @@ function createboard() {
};
}
const BoardView = () => {
let bname = '';
let bimage = '';
@ -187,109 +185,113 @@ const BoardView = () => {
plist = Data.Posts[v.attrs.id];
}
},
view: (v) =>
view: (v) => [
m(
'.widget',
'a[title=Back]',
{
key: v.attrs.id,
onclick: () =>
m.route.set('/boards/:tab', {
tab: m.route.param().tab,
}),
},
[
m(
'a[title=Back]',
{
onclick: () =>
m.route.set('/boards/:tab', {
tab: m.route.param().tab,
}),
},
m('i.fas.fa-arrow-left')
),
m('h3', bname),
m(
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsposted/subscribeToBoard', {
boardId: v.attrs.id,
subscribe: !bsubscribed,
});
if (res.body.retval) {
bsubscribed = !bsubscribed;
Data.DisplayBoards[v.attrs.id].isSubscribed = bsubscribed;
}
},
},
bsubscribed ? 'Subscribed' : 'Subscribe'
),
m('img.boardpic', {
src: 'data:image/png;base64,' + bimage.mData.base64,
}),
m('[id=boarddetails]', [
m('p', m('b', 'Posts: '), bposts),
m(
'p',
m('b', 'Date created: '),
typeof createDate === 'object'
? new Date(createDate.xint64 * 1000).toLocaleString()
: 'undefined'
),
m('p', m('b', 'Admin: '), bauthor),
m(
'p',
m('b', 'Last activity: '),
typeof lastActivity === 'object'
? new Date(lastActivity.xint64 * 1000).toLocaleString()
: 'undefined'
),
]),
m('hr'),
m('boarddesc', m('b', 'Description: '), Data.DisplayBoards[v.attrs.id].description),
m('hr'),
m(
'postdetails',
{
style: 'display:' + (bsubscribed ? 'block' : 'none'),
},
m('h3', 'Posts'),
m(
'[id=grid]',
Object.keys(plist).map((key, index) => [
m(
'div',
{
class: 'card',
style: 'display: ' + (plist[key].isSearched? 'block': 'none'),
onclick: () => {
m.route.set('/boards/:tab/:mGroupId/:mMsgId', {
tab: m.route.param().tab,
mGroupId: v.attrs.id,
mMsgId: key,
});
},
},
[
m('img', {
class: 'card-img',
src: 'data:image/png;base64,' + plist[key].post.mThumbnail.mData.base64,
alt: 'No Thumbnail',
}),
m('div', { class: 'card-info' }, [
m('h4', { class: 'card-title' }, plist[key].post.mMeta.mMsgName),
]),
]
),
])
)
),
]
m('i.fas.fa-arrow-left')
),
m('.widget__heading', [
m('h3', bname),
m(
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsposted/subscribeToBoard', {
boardId: v.attrs.id,
subscribe: !bsubscribed,
});
if (res.body.retval) {
bsubscribed = !bsubscribed;
Data.DisplayBoards[v.attrs.id].isSubscribed = bsubscribed;
}
},
},
bsubscribed ? 'Subscribed' : 'Subscribe'
),
]),
m('.widget__body', [
m('.media-item', [
m('.media-item__details', [
m('img', {
src:
bimage.mData.base64 === ''
? 'data/streaming.png'
: `data:image/png;base64,${bimage.mData.base64}`,
}),
m('.media-item__details-info', [
m('div', [m('b', 'Posts: '), m('span', bposts)]),
m('div', [
m('b', 'Date created: '),
m(
'span',
typeof createDate === 'object'
? new Date(createDate.xint64 * 1000).toLocaleString()
: 'Unknown'
),
]),
m('div', [m('b', 'Admin: '), m('span', bauthor)]),
m('div', [
m('b', 'Last activity: '),
m(
'span',
typeof lastActivity === 'object'
? new Date(lastActivity.xint64 * 1000).toLocaleString()
: 'Unknown'
),
]),
]),
]),
m('.media-item__desc', [
m('b', 'Description: '),
m('span', Data.DisplayBoards[v.attrs.id].description || 'No Description'),
]),
]),
m(
'.posts',
{
style: 'display:' + (bsubscribed ? 'flex' : 'none'),
},
m('.posts__heading', m('h3', 'Posts')),
m(
'.posts-container',
Object.keys(plist).map((key, index) => [
m(
'.posts-container-card',
{
style: 'display: ' + (plist[key].isSearched ? 'flex' : 'none'),
onclick: () => {
m.route.set('/boards/:tab/:mGroupId/:mMsgId', {
tab: m.route.param().tab,
mGroupId: v.attrs.id,
mMsgId: key,
});
},
},
[
m('img', {
src:
plist[key].post.mThumbnail.mData.base64 === ''
? 'data/streaming.png'
: 'data:image/png;base64,' + plist[key].post.mThumbnail.mData.base64,
alt: 'No Thumbnail',
}),
m('p', plist[key].post.mMeta.mMsgName),
]
),
])
)
),
]),
],
};
};
module.exports = {
BoardView,
createboard,

View File

@ -5,14 +5,13 @@ const util = require('boards/boards_util');
const viewUtil = require('boards/board_view');
const peopleUtil = require('people/people_util');
const getBoards =
{
All : [],
PopularBoards : [],
SubscribedBoards : [],
MyBoards : [],
OtherBoards : [],
async load(){
const getBoards = {
All: [],
PopularBoards: [],
SubscribedBoards: [],
MyBoards: [],
OtherBoards: [],
async load() {
const res = await rs.rsJsonApiRequest('/rsPosted/getBoardsSummaries');
const data = res.body;
getBoards.All = data.groupInfo;
@ -21,11 +20,10 @@ const getBoards =
getBoards.OtherBoards = getBoards.PopularBoards.slice(5);
getBoards.PopularBoards = getBoards.PopularBoards.slice(0, 5);
getBoards.SubscribedBoards = getBoards.All.filter(
(board) =>
board.mSubscribeFlags === util.GROUP_SUBSCRIBE_SUBSCRIBED
(board) => board.mSubscribeFlags === util.GROUP_SUBSCRIBE_SUBSCRIBED
);
getBoards.MyBoards = getBoards.All.filter(
(board) => board.mSubscribeFlags === util.GROUP_MY_BOARD
(board) => board.mSubscribeFlags === util.GROUP_MY_BOARD
);
},
};
@ -34,7 +32,7 @@ const sections = {
MyBoards: require('boards/my_boards'),
SubscribedBoards: require('boards/subscribed_boards'),
PopularBoards: require('boards/popular_boards'),
OtherBoards: require('boards/other_boards')
OtherBoards: require('boards/other_boards'),
};
const Layout = () => {
@ -56,49 +54,49 @@ const Layout = () => {
});
},
view: (vnode) =>
m('.tab-page', [
m(util.SearchBar, {
list: getBoards.All,
}),
m(
'button',
{
style: {fontSize: '1.2em', width: '200px'},
onclick: () =>
ownId && util.popupmessage(
m(viewUtil.createboard, {
authorId: ownId,
})
),
},
'Create Board'
),
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/boards/',
}),
m('.board-node-panel',
Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId')
? m(viewUtil.PostView, {
msgId: vnode.attrs.pathInfo.mMsgId,
forumId: vnode.attrs.pathInfo.mGroupId,
})
: Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId')
? m(viewUtil.BoardView, {
id: vnode.attrs.pathInfo.mGroupId,
})
: m(sections[vnode.attrs.pathInfo.tab], {
list: getBoards[vnode.attrs.pathInfo.tab],
})
),
m('.widget', [
m('.top-heading', [
m(
'button',
{
onclick: () =>
ownId &&
util.popupmessage(
m(viewUtil.createboard, {
authorId: ownId,
})
),
},
'Create Board'
),
m(util.SearchBar, {
list: getBoards.All,
}),
]),
Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId')
? m(viewUtil.PostView, {
msgId: vnode.attrs.pathInfo.mMsgId,
forumId: vnode.attrs.pathInfo.mGroupId,
})
: Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId')
? m(viewUtil.BoardView, {
id: vnode.attrs.pathInfo.mGroupId,
})
: m(sections[vnode.attrs.pathInfo.tab], {
list: getBoards[vnode.attrs.pathInfo.tab],
}),
]),
};
};
module.exports = {
view: (vnode) => {
return m(Layout, {
pathInfo: vnode.attrs,
});
return [
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/boards/',
}),
m('.node-panel', m(Layout, { pathInfo: vnode.attrs })),
];
},
};

View File

@ -4,9 +4,8 @@ const util = require('boards/boards_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'My Boards'),
m('hr'),
m('.widget__heading', m('h3', 'My Boards')),
m('.widget__body', [
m(
util.BoardTable,
m('tbody', [

View File

@ -4,9 +4,8 @@ const util = require('boards/boards_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Other Boards'),
m('hr'),
m('.widget__heading', m('h3', 'Other Boards')),
m('.widget__body', [
m(
util.BoardTable,
m('tbody', [

View File

@ -4,9 +4,8 @@ const util = require('boards/boards_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Popular Boards'),
m('hr'),
m('.widget__heading', m('h3', 'Popular Boards')),
m('.widget__body', [
m(
util.BoardTable,
m('tbody', [
@ -14,13 +13,13 @@ const Layout = () => {
m(util.BoardSummary, {
details: board,
category: 'PopularBoards',
}),
})
),
v.attrs.list.map((board) =>
m(util.DisplayBoardsFromList, {
id: board.mGroupId,
category: 'PopularBoards',
}),
})
),
])
),
@ -30,4 +29,3 @@ const Layout = () => {
};
module.exports = Layout;

View File

@ -4,9 +4,8 @@ const util = require('boards/boards_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Subscribed Boards'),
m('hr'),
m('.widget__heading', m('h3', 'Subscribed Boards')),
m('.widget__body', [
m(
util.BoardTable,
m('tbody', [
@ -14,13 +13,13 @@ const Layout = () => {
m(util.BoardSummary, {
details: board,
category: 'SubscribedBoards',
}),
})
),
v.attrs.list.map((board) =>
m(util.DisplayBoardsFromList, {
id: board.mGroupId,
category: 'SubscribedBoards',
}),
})
),
])
),
@ -30,4 +29,3 @@ const Layout = () => {
};
module.exports = Layout;

View File

@ -74,7 +74,7 @@ async function parsefile(file, type) {
return ansList;
}
const messageGroups = ['Public', 'Restricted Circle', 'Restricted Node Group'];
const messageGroupsCode = [util.PUBLIC, util.EXTERNAL, util.NODES_GROUP]; //rsgxscirles.h:50
const messageGroupsCode = [util.PUBLIC, util.EXTERNAL, util.NODES_GROUP]; // rsgxscirles.h:50
function createchannel() {
let title;
@ -200,10 +200,10 @@ function createchannel() {
name: title,
description: body,
thumbnail: { mData: { base64: thumbnail } },
...(Number(identity) !== 0 && { authorId: identity }), //checks if some identity has to be assigned
...(Number(identity) !== 0 && { authorId: identity }), // checks if some identity has to be assigned
circleType: selectedGroupCode,
...(selectedGroupCode === util.EXTERNAL &&
selectedCircle && { circleId: selectedCircle.mGroupId }), //checks if the selectedGroup code is EXTERNAL
selectedCircle && { circleId: selectedCircle.mGroupId }), // checks if the selectedGroup code is EXTERNAL
});
if (res.body.retval) {
util.updatedisplaychannels(res.body.channelId);
@ -287,7 +287,7 @@ const AddPost = () => {
channelId: vnode.attrs.chanId,
title: ptitle,
mBody: content,
files: pfiles, //does not work for now
files: pfiles, // does not work for now
thumbnail: { mData: { base64: pthumbnail } },
});
res.body.retval === false
@ -340,90 +340,95 @@ const ChannelView = () => {
plist = Data.Posts[v.attrs.id];
}
},
view: (v) =>
view: (v) => [
m(
'.widget',
'a[title=Back]',
{
key: v.attrs.id,
onclick: () =>
m.route.set('/channels/:tab', {
tab: m.route.param().tab,
}),
},
[
m(
'a[title=Back]',
{
onclick: () =>
m.route.set('/channels/:tab', {
tab: m.route.param().tab,
}),
m('i.fas.fa-arrow-left')
),
m('.widget__heading', [
m('h3', cname),
m(
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsgxschannels/subscribeToChannel', {
channelId: v.attrs.id,
subscribe: !csubscribed,
});
if (res.body.retval) {
csubscribed = !csubscribed;
Data.DisplayChannels[v.attrs.id].isSubscribed = csubscribed;
}
},
m('i.fas.fa-arrow-left')
),
m('h3', cname),
m(
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsgxschannels/subscribeToChannel', {
channelId: v.attrs.id,
subscribe: !csubscribed,
});
if (res.body.retval) {
csubscribed = !csubscribed;
Data.DisplayChannels[v.attrs.id].isSubscribed = csubscribed;
}
},
},
csubscribed ? 'Subscribed' : 'Subscribe'
),
m('img.channelpic', {
src:
cimage.mData.base64 === ''
? 'data/streaming.png'
: 'data:image/png;base64,' + cimage.mData.base64,
}),
m('[id=channeldetails]', [
m('p', m('b', 'Posts: '), cposts),
m(
'p',
m('b', 'Date created: '),
typeof createDate === 'object'
? new Date(createDate.xint64 * 1000).toLocaleString()
: 'undefined'
),
m('p', m('b', 'Admin: '), cauthor),
m(
'p',
m('b', 'Last activity: '),
typeof lastActivity === 'object'
? new Date(lastActivity.xint64 * 1000).toLocaleString()
: 'undefined'
),
},
csubscribed ? 'Subscribed' : 'Subscribe'
),
]),
m('.widget__body', [
m('.media-item', [
m('.media-item__details', [
m('img', {
src:
cimage.mData.base64 === ''
? 'data/streaming.png'
: `data:image/png;base64,${cimage.mData.base64}`,
}),
m('.media-item__details-info', [
m('div', [m('b', 'Posts: '), m('span', cposts)]),
m('div', [
m('b', 'Date created: '),
m(
'span',
typeof createDate === 'object'
? new Date(createDate.xint64 * 1000).toLocaleString()
: 'Unknown'
),
]),
m('div', [m('b', 'Admin: '), m('span', cauthor)]),
m('div', [
m('b', 'Last activity: '),
m(
'span',
typeof lastActivity === 'object'
? new Date(lastActivity.xint64 * 1000).toLocaleString()
: 'Unknown'
),
]),
]),
]),
m('hr'),
m('channeldesc', m('b', 'Description: '), Data.DisplayChannels[v.attrs.id].description),
m('hr'),
m(
'postdetails',
{
style: 'display:' + (csubscribed ? 'block' : 'none'),
},
m('h3', 'Posts'),
mychannel &&
m(
'button',
{ onclick: () => widget.popupMessage(m(AddPost, { chanId: v.attrs.id })) },
['Add Post', m('i.fas.fa-edit')]
),
m('hr'),
m('.media-item__desc', [
m('b', 'Description: '),
m('span', Data.DisplayChannels[v.attrs.id].description || 'No Description'),
]),
]),
m(
'.posts',
{
style: 'display: ' + (csubscribed ? 'flex' : 'none'),
},
[
m('.posts__heading', [
m('h3', 'Posts'),
mychannel &&
m(
'button',
{ onclick: () => widget.popupMessage(m(AddPost, { chanId: v.attrs.id })) },
['Add Post', m('i.fas.fa-edit')]
),
]),
m(
'[id=grid]',
'.posts-container',
Object.keys(plist).map((key, index) => [
m(
'div',
'.posts-container-card',
{
class: 'card',
style: 'display: ' + (plist[key].isSearched ? 'block' : 'none'), // for search
style: 'display: ' + (plist[key].isSearched ? 'flex' : 'none'), // for search
onclick: () => {
m.route.set('/channels/:tab/:mGroupId/:mMsgId', {
tab: m.route.param().tab,
@ -434,24 +439,21 @@ const ChannelView = () => {
},
[
m('img', {
class: 'card-img',
src:
plist[key].post.mThumbnail.mData.base64 === ''
? 'data/streaming.png'
: 'data:image/png;base64,' + plist[key].post.mThumbnail.mData.base64,
alt: '',
alt: 'No Thumbnail',
}),
m('div', { class: 'card-info' }, [
m('h4', { class: 'card-title' }, plist[key].post.mMeta.mMsgName),
]),
m('p', plist[key].post.mMeta.mMsgName),
]
),
])
)
),
]
),
),
]
),
]),
],
};
};
@ -544,14 +546,16 @@ function displaycomment() {
oninit: (v) => {},
view: ({ attrs: { commentStruct, identity, replyDepth, voteIdentity } }) => {
const comment = commentStruct.comment;
let cUpVotes = 0;
let cUpVotes = 0;
let cDownVotes = 0;
let parMap = {};
if (Data.ParentCommentMap[comment.mMeta.mMsgId]) {
parMap = Data.ParentCommentMap[comment.mMeta.mMsgId];
}
if(Data.Votes[comment.mMeta.mThreadId] && Data.Votes[comment.mMeta.mThreadId][comment.mMeta.mMsgId])
{
if (
Data.Votes[comment.mMeta.mThreadId] &&
Data.Votes[comment.mMeta.mThreadId][comment.mMeta.mMsgId]
) {
cUpVotes = Data.Votes[comment.mMeta.mThreadId][comment.mMeta.mMsgId].upvotes;
cDownVotes = Data.Votes[comment.mMeta.mThreadId][comment.mMeta.mMsgId].downvotes;
}
@ -695,132 +699,132 @@ const PostView = () => {
});
fileDown.Downloads.loadStatus(); // for retrieving downloading files.
},
view: (v) =>
m('.widget', { key: v.attrs.msgId }, [
m(
'a[title=Back]',
{
onclick: () =>
m.route.set('/channels/:tab/:mGroupId', {
tab: m.route.param().tab,
mGroupId: m.route.param().mGroupId,
}),
},
m('i.fas.fa-arrow-left')
),
m('h3', post.mMeta.mMsgName),
m('p', m.trust(post.mMsg)),
m('hr'),
m('h3', 'Files(' + post.mAttachmentCount + ')'),
m(
util.FilesTable,
view: (v) => [
m(
'a[title=Back]',
{
onclick: () =>
m.route.set('/channels/:tab/:mGroupId', {
tab: m.route.param().tab,
mGroupId: m.route.param().mGroupId,
}),
},
m('i.fas.fa-arrow-left')
),
m('.widget__heading', m('h3', post.mMeta.mMsgName)),
m('.widget__body', [
m('p', { style: { whiteSpace: 'normal' } }, m.trust(post.mMsg)),
m('.file-section', [
m('h3', 'Files(' + post.mAttachmentCount + ')'),
m(
'tbody',
post.mFiles.map((file) =>
m('tr', [
m('td', file.mName),
m('td', util.formatbytes(file.mSize.xint64)),
m(
'button',
{
style: { fontSize: '0.9em' },
onclick: async () =>
widget.popupMessage([
m('p', 'Start Download?'),
m(
'button',
{
onclick: async () => {
if (filesInfo[file.mHash] && !filesInfo[file.mHash].retval) {
const res = await rs.rsJsonApiRequest('/rsFiles/FileRequest', {
fileName: file.mName,
hash: file.mHash,
flags: util.RS_FILE_REQ_ANONYMOUS_ROUTING,
size: {
xstr64: file.mSize.xstr64,
},
});
res.body.retval === false
? widget.popupMessage([
m('h3', 'Error'),
m('hr'),
m('p', res.body.errorMessage),
])
: widget.popupMessage([
m('h3', 'Success'),
m('hr'),
m('p', 'Download Started'),
]);
m.redraw();
}
util.FilesTable,
m(
'tbody',
post.mFiles.map((file) =>
m('tr', [
m('td', file.mName),
m('td', util.formatbytes(file.mSize.xint64)),
m(
'button',
{
style: { fontSize: '0.9em' },
onclick: async () =>
widget.popupMessage([
m('p', 'Start Download?'),
m(
'button',
{
onclick: async () => {
if (filesInfo[file.mHash] && !filesInfo[file.mHash].retval) {
const res = await rs.rsJsonApiRequest('/rsFiles/FileRequest', {
fileName: file.mName,
hash: file.mHash,
flags: util.RS_FILE_REQ_ANONYMOUS_ROUTING,
size: {
xstr64: file.mSize.xstr64,
},
});
res.body.retval === false
? widget.popupMessage([
m('h3', 'Error'),
m('hr'),
m('p', res.body.errorMessage),
])
: widget.popupMessage([
m('h3', 'Success'),
m('hr'),
m('p', 'Download Started'),
]);
m.redraw();
}
},
},
},
'Start Download'
),
]),
},
filesInfo[file.mHash]
? filesInfo[file.mHash].retval
? 'Open File'
: ['Download', m('i.fas.fa-download')]
: 'Please Wait...'
),
fileDown.list[file.mHash] && // using the file from files_util to display download.
m(fileUtil.File, {
info: fileDown.list[file.mHash],
direction: 'down',
transferred: fileDown.list[file.mHash].transfered.xint64,
parts: [],
}),
])
'Start Download'
),
]),
},
filesInfo[file.mHash]
? filesInfo[file.mHash].retval
? 'Open File'
: ['Download', m('i.fas.fa-download')]
: 'Please Wait...'
),
fileDown.list[file.mHash] && // using the file from files_util to display download.
m(fileUtil.File, {
info: fileDown.list[file.mHash],
direction: 'down',
transferred: fileDown.list[file.mHash].transfered.xint64,
parts: [],
}),
])
)
)
)
),
m('hr'),
m('h3', 'Comments'),
m(
'button',
{
onclick: () => {
widget.popupMessage(
m(AddComment, {
parent_comment: '',
channelId: v.attrs.channelId,
authorId: ownId,
threadId: v.attrs.msgId,
parentId: v.attrs.msgId,
})
);
},
},
'Add Comment'
),
m(
'label[for=idtags',
{
style: { marginLeft: '10px' },
},
'Voter ID: '
),
m(
'select[id=idtags]',
{
value: voteIdentity,
onchange: (e) => {
voteIdentity = ownId[e.target.selectedIndex];
},
},
[
ownId &&
ownId.map((o) =>
m(
'option',
{ value: o },
rs.userList.userMap[o].toLocaleString() + ' (' + o.slice(0, 8) + '...)'
)
),
]),
m('.comments-section', [
m('h3', 'Comments'),
m('.comments-section__menu', [
m(
'button',
{
onclick: () => {
widget.popupMessage(
m(AddComment, {
parent_comment: '',
channelId: v.attrs.channelId,
authorId: ownId,
threadId: v.attrs.msgId,
parentId: v.attrs.msgId,
})
);
},
},
'Add Comment'
),
m('.comments-section__menu-id', [
m('label[for=idtags', 'Voter ID: '),
m(
'select[id=idtags]',
{
value: voteIdentity,
onchange: (e) => {
voteIdentity = ownId[e.target.selectedIndex];
},
},
[
ownId &&
ownId.map((o) =>
m(
'option',
{ value: o },
`${rs.userList.userMap[o].toLocaleString()} (${o.slice(0, 8)}...)`
)
),
]
),
]
),
]),
]),
]),
m(
util.CommentsTable,
m(
@ -843,6 +847,7 @@ const PostView = () => {
)
),
]),
],
};
};

View File

@ -61,60 +61,57 @@ const Layout = () => {
},
// onupdate: getChannels.load,
view: (vnode) =>
m('.tab-page', [
Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId')
? ''
: Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId')
? m(util.SearchBar, {
category: 'posts',
channelId: vnode.attrs.pathInfo.mGroupId,
})
: m(util.SearchBar, {
category: 'channels',
}),
m(
'button',
{
style: { fontSize: '1.2em', width: '200px' },
onclick: () =>
ownId &&
widget.popupMessage(
m(viewUtil.createchannel, {
authorId: ownId,
})
),
},
'Create Channel'
),
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/channels/',
}),
m(
'.channel-node-panel',
Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId') // posts
? m(viewUtil.PostView, {
msgId: vnode.attrs.pathInfo.mMsgId,
m('.widget', [
m('.top-heading', [
m(
'button',
{
onclick: () =>
ownId &&
widget.popupMessage(
m(viewUtil.createchannel, {
authorId: ownId,
})
),
},
'Create Channel'
),
Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId')
? ''
: Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId')
? m(util.SearchBar, {
category: 'posts',
channelId: vnode.attrs.pathInfo.mGroupId,
})
: Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId') // channels view
? m(viewUtil.ChannelView, {
id: vnode.attrs.pathInfo.mGroupId,
})
: m(sections[vnode.attrs.pathInfo.tab], {
// subscribed, all, popular, other
list: getChannels[vnode.attrs.pathInfo.tab],
})
),
: m(util.SearchBar, {
category: 'channels',
}),
]),
Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId') // posts
? m(viewUtil.PostView, {
msgId: vnode.attrs.pathInfo.mMsgId,
channelId: vnode.attrs.pathInfo.mGroupId,
})
: Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId') // channels view
? m(viewUtil.ChannelView, {
id: vnode.attrs.pathInfo.mGroupId,
})
: m(sections[vnode.attrs.pathInfo.tab], {
// subscribed, all, popular, other
list: getChannels[vnode.attrs.pathInfo.tab],
}),
]),
};
};
module.exports = {
view: (vnode) => {
return m(Layout, {
pathInfo: vnode.attrs,
});
return [
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/channels/',
}),
m('.node-panel', m(Layout, { pathInfo: vnode.attrs })),
];
},
};

View File

@ -17,9 +17,9 @@ const RS_FILE_REQ_ANONYMOUS_ROUTING = 0x00000040;
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 = {
@ -201,7 +201,7 @@ const SearchBar = () => {
let searchString = '';
return {
view: (v) =>
m('input[type=text][id=searchchannel][placeholder=Search Subject].searchbar', {
m('input[type=text][placeholder=Search Subject].searchbar', {
value: searchString,
placeholder:
v.attrs.category.localeCompare('channels') === 0 ? 'Search Channels' : 'Search Posts',

View File

@ -4,9 +4,8 @@ const util = require('channels/channels_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'My Channels'),
m('hr'),
m('.widget__heading', m('h3', 'My Channels')),
m('.widget__body', [
m(
util.ChannelTable,
m('tbody', [

View File

@ -4,9 +4,8 @@ const util = require('channels/channels_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Other Channels'),
m('hr'),
m('.widget__heading', m('h3', 'Other Channels')),
m('.widget__body', [
m(
util.ChannelTable,
m('tbody', [

View File

@ -4,9 +4,8 @@ const util = require('channels/channels_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Popular Channels'),
m('hr'),
m('.widget__heading', m('h3', 'Popular Channels')),
m('.widget__body', [
m(
util.ChannelTable,
m('tbody', [

View File

@ -4,9 +4,8 @@ const util = require('channels/channels_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Subscribed Channels'),
m('hr'),
m('.widget__heading', m('h3', 'Subscribed Channels')),
m('.widget__body', [
m(
util.ChannelTable,
m('tbody', [

View File

@ -297,7 +297,6 @@ const LobbyList = {
const lobbytagname = vnode.attrs.lobbytagname;
const onclick = vnode.attrs.onclick || (() => null);
return [
m('hr'),
vnode.attrs.rooms.map((info) =>
m(Lobby, {
info,
@ -327,12 +326,14 @@ const SubscribedLeftLobbies = {
const SubscribedLobbies = {
view() {
return m('.widget', [
m('h3', 'Subscribed chat rooms'),
m(LobbyList, {
rooms: sortLobbies(Object.values(ChatRoomsModel.subscribedRooms)),
tagname: '.lobby.subscribed',
onclick: ChatLobbyModel.switchToEvent,
}),
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,
}),
]),
]);
},
};
@ -355,12 +356,14 @@ const PublicLeftLobbies = {
const PublicLobbies = () => {
return m('.widget', [
m('h3', 'Public chat rooms'),
m(LobbyList, {
rooms: ChatRoomsModel.allRooms.filter((info) => !ChatRoomsModel.subscribed(info)),
tagname: '.lobby.public',
onclick: ChatLobbyModel.setupEvent,
}),
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,
}),
]),
]);
};
@ -405,7 +408,7 @@ const LobbyName = () => {
const Layout = () => {
return {
view: () => m('.tab-page', [m(SubscribedLobbies), PublicLobbies()]),
view: () => m('.node-panel', [m(SubscribedLobbies), PublicLobbies()]),
};
};
@ -413,7 +416,7 @@ const LayoutSingle = () => {
return {
oninit: () => ChatLobbyModel.loadLobby(m.route.param('lobby')),
view: (vnode) =>
m('.tab-page', [
m('.node-panel', [
LobbyName(),
m('.lobbies', m(SubscribedLeftLobbies), m(PublicLeftLobbies)),
m('.messages', ChatLobbyModel.messages),
@ -442,7 +445,7 @@ const LayoutSetup = () => {
return {
oninit: () => peopleUtil.ownIds((data) => (ownIds = data)),
view: (vnode) =>
m('.tab-page', [
m('.node-panel', [
LobbyName(),
m('.lobbies', m(SubscribedLeftLobbies), m(PublicLeftLobbies)),
m('.setup', [
@ -475,7 +478,7 @@ const LayoutCreateDistant = () => {
return {
oninit: () => peopleUtil.ownIds((data) => (ownIds = data)),
view: (vnode) =>
m('.tab-page', [
m('.node-panel', [
m('.createDistantChat', [
'choose identitiy to chat with ',
rs.userList.username(m.route.param('lobby')),

View File

@ -9,9 +9,8 @@ const SharedDirectories = () => {
rs.rsJsonApiRequest('/rsFiles/getSharedDirectories', {}, (data) => (directories = data.dirs));
},
view: () =>
m('.widget', [
m('h3', 'Shared Directories'),
m('hr'),
m('.widget__body-box', [
m('.widget__heading', m('h3', 'Shared Directories')),
directories.map((dir) =>
m('input[type=text].stretched', {
value: dir.filename,
@ -33,9 +32,8 @@ const DownloadDirectory = () => {
rs.rsJsonApiRequest('/rsFiles/getDownloadDirectory', {}, (data) => (dlDir = data.retval));
},
view: () =>
m('.widget', [
m('h3', 'Downloads Directory'),
m('hr'),
m('.widget__body-box', [
m('.widget__heading', m('h3', 'Downloads Directory')),
m('input[type=text].stretched#dl-dir-input', {
oninput: (e) => (dlDir = e.target.value),
value: dlDir,
@ -62,9 +60,8 @@ const PartialsDirectory = () => {
(data) => (partialsDir = data.retval)
),
view: () =>
m('.widget.widget-halfwidth', [
m('h3', 'Partials Directory'),
m('hr'),
m('.widget__body-box', [
m('.widget__heading', m('h3', 'Partials Directory')),
m('input[type=text].stretched#partial-dir-input', {
oninput: (e) => (partialsDir = e.target.value),
value: partialsDir,
@ -123,9 +120,8 @@ const TransferOptions = () => {
);
},
view: () =>
m('.widget.widget-half', [
m('h3', 'Transfer options'),
m('hr'),
m('.widget__body-box', [
m('.widget__heading', m('h3', 'Transfer options')),
m('.grid-2col', [
m('p', 'Maximum simultaneous downloads:'),
m('input[type=number]', {
@ -221,13 +217,17 @@ const TransferOptions = () => {
const Layout = () => {
return {
view: () => [
m(SharedDirectories),
m(DownloadDirectory),
m(PartialsDirectory),
m(TransferOptions),
],
view: () =>
m('.widget', [
m('.widget__heading', m('h3', 'Files Configuration')),
m('.widget__body.config-files', [
m(SharedDirectories),
m(DownloadDirectory),
m(PartialsDirectory),
m(TransferOptions),
]),
]),
};
};
module.exports = Layout;
module.exports = Layout;

View File

@ -76,111 +76,110 @@ const Mail = () => {
);
},
view: () =>
m('.widget.widget-half.mail', [
m('.mail-tags__heading', m('h3', 'Distant Messages')),
m('hr'),
m('.permission-flag', [
m('p', 'Accept encrypted distant messages from: '),
m(
'select[id=setDistantMessagingPermission]',
{
value: distantMessagingPermissionFlag,
oninput: (e) => (distantMessagingPermissionFlag = e.target.value),
onchange: () => {
rs.rsJsonApiRequest('/rsMsgs/setDistantMessagingPermissionFlags', {
flags: parseInt(distantMessagingPermissionFlag),
});
m('.widget.mail', [
m('.widget__heading', m('h3', 'Mail Configuration')),
m('.widget__body', [
m('.permission-flag', [
m('p', 'Accept encrypted distant messages from: '),
m(
'select',
{
value: distantMessagingPermissionFlag,
oninput: (e) => (distantMessagingPermissionFlag = e.target.value),
onchange: () => {
rs.rsJsonApiRequest('/rsMsgs/setDistantMessagingPermissionFlags', {
flags: parseInt(distantMessagingPermissionFlag),
});
},
},
},
[
m(
'option',
{
value: util.RS_DISTANT_MESSAGING_PERMISSION_FLAG_FILTER_NONE,
[
m(
'option',
{
value: util.RS_DISTANT_MESSAGING_PERMISSION_FLAG_FILTER_NONE,
},
'Everybody'
),
m(
'option',
{
value: util.RS_DISTANT_MESSAGING_PERMISSION_FLAG_FILTER_NON_CONTACTS,
},
'Contacts'
),
m(
'option',
{
value: util.RS_DISTANT_MESSAGING_PERMISSION_FLAG_FILTER_EVERYBODY,
},
'Nobody'
),
]
),
]),
m('.widget__heading', [
m('h3', 'Mail Tags'),
m(
'button',
{
onclick: () => {
// set form fields to default values
msgTagObj.tagName = '';
msgTagObj.tagColor = '';
widget.popupMessage(m(MessageTagForm));
},
'Everybody'
),
m(
'option',
{
value: util.RS_DISTANT_MESSAGING_PERMISSION_FLAG_FILTER_NON_CONTACTS,
},
'Contacts'
),
m(
'option',
{
value: util.RS_DISTANT_MESSAGING_PERMISSION_FLAG_FILTER_EVERYBODY,
},
'Nobody'
),
]
),
]),
m('br'),
m('.mail-tags__heading', [
m('h3', 'Mail Tags'),
m(
'button',
{
onclick: () => {
// set form fields to default values
msgTagObj.tagName = '';
msgTagObj.tagColor = '';
widget.popupMessage(m(MessageTagForm));
},
},
'Create New Tag'
),
]),
m('hr'),
m(
'div.mail-tags',
tagArr.length === 0
? m('h4', 'No Message Tags')
: m(
'div.mail-tags__container',
tagArr.map((tag) =>
m('.tag-item', { key: tag.key }, [
m('div.tag-item__color', {
style: {
backgroundColor: `#${tag.value.second.toString(16).padStart(6, '0')}`,
},
}),
m('p.tag-item__name', tag.value.first),
m('.tag-item__modify', [
m(
'button',
{
onclick: () => {
msgTagObj.tagName = tag.value.first;
msgTagObj.tagColor = `#${tag.value.second
.toString(16)
.padStart(6, '0')}`;
widget.popupMessage(m(MessageTagForm, { tagItem: tag }));
},
'Create New Tag'
),
]),
m(
'.mail-tags',
tagArr.length === 0
? m('h4', 'No Message Tags')
: m(
'.mail-tags__container',
tagArr.map((tag) =>
m('.tag-item', { key: tag.key }, [
m('.tag-item__color', {
style: {
backgroundColor: `#${tag.value.second.toString(16).padStart(6, '0')}`,
},
m('i.fas.fa-pen')
),
m(
'button.red',
{
onclick: () => {
rs.rsJsonApiRequest('/rsMsgs/removeMessageTagType', {
tagId: tag.key,
}).then((res) => {
if (res.body.retval)
tagArr = tagArr.filter((item) => item.key !== tag.key);
});
}),
m('p.tag-item__name', tag.value.first),
m('.tag-item__modify', [
m(
'button',
{
onclick: () => {
msgTagObj.tagName = tag.value.first;
msgTagObj.tagColor = `#${tag.value.second
.toString(16)
.padStart(6, '0')}`;
widget.popupMessage(m(MessageTagForm, { tagItem: tag }));
},
},
},
m('i.fas.fa-trash')
),
]),
])
m('i.fas.fa-pen')
),
m(
'button.red',
{
onclick: () => {
rs.rsJsonApiRequest('/rsMsgs/removeMessageTagType', {
tagId: tag.key,
}).then((res) => {
if (res.body.retval)
tagArr = tagArr.filter((item) => item.key !== tag.key);
});
},
},
m('i.fas.fa-trash')
),
]),
])
)
)
)
),
),
]),
]),
};
};

View File

@ -332,7 +332,7 @@ const SetSocksProxy = () => {
),
Object.keys(socksProxyObj).map((proxyItem) => {
return m(`.proxy-server__${proxyItem}`, [
m('h4', `${proxyItem.toUpperCase()} Socks Proxy: `),
m('h6', `${proxyItem.toUpperCase()} Socks Proxy: `),
m('input[type=text]', {
value: socksProxyObj[proxyItem].addr,
oninput: (e) => (socksProxyObj[proxyItem].addr = e.target.value),
@ -379,27 +379,24 @@ const Component = () => {
}
});
},
view: () => [
m('.widget.widget-half', [
m('h3', 'Network Configuration'),
m('hr'),
m('.grid-2col', [
m(SetNwMode),
m(SetNAT),
m(displayLocalIPAddress, { details }),
m(displayExternalIPAddress, { details }),
m(SetDynamicDNS),
m(SetLimits),
m(SetOpMode),
m(displayIPAddresses, { details }),
view: () =>
m('.widget', [
m('.widget__heading', m('h3', 'Network Configuration')),
m('.widget__body', [
m('.grid-2col', [
m(SetNwMode),
m(SetNAT),
m(displayLocalIPAddress, { details }),
m(displayExternalIPAddress, { details }),
m(SetDynamicDNS),
m(SetLimits),
m(SetOpMode),
m(displayIPAddresses, { details }),
]),
m('.widget__heading', m('h3', 'Hidden Service Configuration')),
m('.widget__body', [m('.grid-2col', [m(SetSocksProxy)])]),
]),
]),
m('.widget.widget-half', [
m('h3', 'Hidden Service Configuration'),
m('hr'),
m('.grid-2col', [m(SetSocksProxy)]),
]),
],
};
};

View File

@ -13,17 +13,18 @@ const Node = () => {
},
view() {
return [
m('.widget.widget-half', [
m('h3', 'Public Information'),
m('hr'),
m('ul', [
m('li', 'Name: ' + nodeInfo.ownName),
m('li', 'Location ID: ' + nodeInfo.ownId),
m('li', 'Firewall: ' + nodeInfo.firewalled),
m('li', 'Port Forwarding: ' + nodeInfo.forwardPort),
m('li', 'DHT: ' + nodeInfo.DHTActive),
m('li', 'uPnP: ' + nodeInfo.uPnPActive),
m('li', 'Local Address: ' + nodeInfo.localAddr + ' Port: ' + nodeInfo.localPort),
m('.widget', [
m('.widget__heading', m('h3', 'Public Information')),
m('.widget__body', [
m('ul', [
m('li', 'Name: ' + nodeInfo.ownName),
m('li', 'Location ID: ' + nodeInfo.ownId),
m('li', 'Firewall: ' + nodeInfo.firewalled),
m('li', 'Port Forwarding: ' + nodeInfo.forwardPort),
m('li', 'DHT: ' + nodeInfo.DHTActive),
m('li', 'uPnP: ' + nodeInfo.uPnPActive),
m('li', 'Local Address: ' + nodeInfo.localAddr + ' Port: ' + nodeInfo.localPort),
]),
]),
]),
];

View File

@ -38,76 +38,77 @@ const Reputation = () => {
},
view: (vnode) =>
m('.widget', [
m('h3', 'Reputation'),
m('hr'),
m('.grid-2col', [
m('p', 'Use "positive" as the default opinion for contacts(instead of neutral):'),
m('input[type=checkbox]', {
checked: usePositiveDefault,
oninput: (e) => {
usePositiveDefault = e.target.checked;
rs.rsJsonApiRequest(
'/rsreputations/setAutoPositiveOpinionForContacts',
{
b: usePositiveDefault,
},
() => {}
);
},
}),
m('p', 'Automatically add identities owned by friend nodes to my contacts:'),
m('input[type=checkbox]', {
checked: addFriendIdAsContacts,
oninput: (e) => {
addFriendIdAsContacts = e.target.checked;
rs.rsJsonApiRequest(
'/rsIdentity/setAutoAddFriendIdsAsContact',
{
enabled: addFriendIdAsContacts,
},
() => {}
);
},
}),
m('p', 'Difference in votes (+/-) to rate an ID positively:'),
m('input[type=number]', {
oninput: (e) => (positiveThreshold = e.target.value),
value: positiveThreshold,
onchange: () =>
rs.rsJsonApiRequest(
'/rsreputations/setThresholdForRemotelyPositiveReputation',
{
thresh: positiveThreshold,
},
() => {}
),
}),
m('p', 'Difference in votes (+/-) to rate an ID negatively:'),
m('input[type=number]', {
oninput: (e) => (negativeThreshold = e.target.value),
value: negativeThreshold,
onchange: () =>
rs.rsJsonApiRequest(
'/rsreputations/setThresholdForRemotelyNegativeReputation',
{
thresh: negativeThreshold,
},
() => {}
),
}),
m('p', 'Delete banned identities after(in days, 0 means indefinitely):'),
m('input[type=number]', {
oninput: (e) => (deleteBannedAfter = e.target.value),
value: deleteBannedAfter,
onchange: () =>
rs.rsJsonApiRequest(
'/rsIdentity/setDeleteBannedNodesThreshold',
{
days: deleteBannedAfter,
},
() => {}
),
}),
m('.widget__heading', m('h3', 'Reputation')),
m('.widget__body', [
m('.grid-2col', [
m('p', 'Use "positive" as the default opinion for contacts(instead of neutral):'),
m('input[type=checkbox]', {
checked: usePositiveDefault,
oninput: (e) => {
usePositiveDefault = e.target.checked;
rs.rsJsonApiRequest(
'/rsreputations/setAutoPositiveOpinionForContacts',
{
b: usePositiveDefault,
},
() => {}
);
},
}),
m('p', 'Automatically add identities owned by friend nodes to my contacts:'),
m('input[type=checkbox]', {
checked: addFriendIdAsContacts,
oninput: (e) => {
addFriendIdAsContacts = e.target.checked;
rs.rsJsonApiRequest(
'/rsIdentity/setAutoAddFriendIdsAsContact',
{
enabled: addFriendIdAsContacts,
},
() => {}
);
},
}),
m('p', 'Difference in votes (+/-) to rate an ID positively:'),
m('input[type=number]', {
oninput: (e) => (positiveThreshold = e.target.value),
value: positiveThreshold,
onchange: () =>
rs.rsJsonApiRequest(
'/rsreputations/setThresholdForRemotelyPositiveReputation',
{
thresh: positiveThreshold,
},
() => {}
),
}),
m('p', 'Difference in votes (+/-) to rate an ID negatively:'),
m('input[type=number]', {
oninput: (e) => (negativeThreshold = e.target.value),
value: negativeThreshold,
onchange: () =>
rs.rsJsonApiRequest(
'/rsreputations/setThresholdForRemotelyNegativeReputation',
{
thresh: negativeThreshold,
},
() => {}
),
}),
m('p', 'Delete banned identities after(in days, 0 means indefinitely):'),
m('input[type=number]', {
oninput: (e) => (deleteBannedAfter = e.target.value),
value: deleteBannedAfter,
onchange: () =>
rs.rsJsonApiRequest(
'/rsIdentity/setDeleteBannedNodesThreshold',
{
days: deleteBannedAfter,
},
() => {}
),
}),
]),
]),
]),
};

View File

@ -1,6 +1,4 @@
const m = require('mithril');
const rs = require('rswebui');
const widget = require('widgets');
const sections = {
@ -13,14 +11,13 @@ const sections = {
};
const Layout = {
view: (vnode) =>
m('.tab-page', [
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/config/',
}),
m('.config-node-panel', vnode.children),
]),
view: (vnode) => [
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/config/',
}),
m('.node-panel', vnode.children),
],
};
module.exports = {

View File

@ -56,28 +56,28 @@ const MyServices = {
},
view() {
return m('.widget', [
m('h3', 'My Services'),
m('hr'),
m('table', [
m('tr', [m('th', 'Name'), m('th', 'ID'), m('th', 'Version'), m('th', 'Allow by default')]),
servicesInfo.list.map((data) =>
m(Service, {
data,
})
),
m('.widget__heading', m('h3', 'My Services')),
m('.widget__body', [
m('table', [
m('tr', [
m('th', 'Name'),
m('th', 'ID'),
m('th', 'Version'),
m('th', 'Allow by default'),
]),
servicesInfo.list.map((data) =>
m(Service, {
data,
})
),
]),
]),
]);
},
};
const Layout = () => {
return {
view: (vnode) => [m(MyServices)],
};
};
module.exports = {
view: (vnode) => {
return m(Layout);
view: () => {
return m(MyServices);
},
};

View File

@ -4,17 +4,24 @@ const util = require('files/files_util');
const widget = require('widgets');
const Downloads = {
strategies: {},
statusMap: {},
hashes: [],
async loadHashes() {
const res = await rs.rsJsonApiRequest(
'/rsFiles/FileDownloads',
{},
(d) => (Downloads.hashes = d.hashs)
loadStrategy() {
rs.rsJsonApiRequest('/rsFiles/FileDownloads', {}, (d) =>
d.hashs.map((hash) => {
rs.rsJsonApiRequest('/rsFiles/getChunkStrategy', { hash }).then((res) => {
if (res.body.retval) Downloads.strategies[hash] = res.body.s;
});
})
);
},
async loadHashes() {
await rs.rsJsonApiRequest('/rsFiles/FileDownloads', {}, (d) => (Downloads.hashes = d.hashs));
},
async loadStatus() {
await Downloads.loadHashes();
const fileKeys = Object.keys(Downloads.statusMap);
@ -132,38 +139,45 @@ const NewFileDialog = () => {
const Component = () => {
return {
oninit: () => {
Downloads.loadStrategy();
rs.setBackgroundTask(Downloads.loadStatus, 1000, () => {
return m.route.get() === '/files/files';
});
Downloads.resetSearch();
},
view: () =>
m('.widget', [
m('h3', 'Downloads (' + Downloads.hashes.length + ' files)'),
m('hr'),
m(
'button',
{
onclick: () => widget.popupMessage(m(NewFileDialog)),
},
'Add new file'
),
m(
'button',
{
onclick: () => rs.rsJsonApiRequest('/rsFiles/FileClearCompleted'),
},
'Clear completed'
),
Object.keys(Downloads.statusMap).map((hash) =>
m(util.File, {
info: Downloads.statusMap[hash],
direction: 'down',
transferred: Downloads.statusMap[hash].transfered.xint64,
parts: [],
})
),
view: () => [
m('.widget__body-heading', [
m('h3', 'Downloads (' + (Downloads.hashes && Downloads.hashes.length) + ' files)'),
m('.action', [
m(
'button',
{
onclick: () => widget.popupMessage(m(NewFileDialog)),
},
'Add new file'
),
m(
'button',
{
onclick: () => rs.rsJsonApiRequest('/rsFiles/FileClearCompleted'),
},
'Clear completed'
),
]),
]),
m('.widget__body-content', [
Downloads.statusMap &&
Object.keys(Downloads.statusMap).map((hash) =>
m(util.File, {
info: Downloads.statusMap[hash],
strategy: Downloads.strategies[hash],
direction: 'down',
transferred: Downloads.statusMap[hash].transfered.xint64,
parts: [],
})
),
]),
],
};
};

View File

@ -11,12 +11,14 @@ const friendfile = require('files/friends_files');
const MyFiles = () => {
return {
view: (vnode) => [
m(util.SearchBar, {
list: Object.assign({}, downloads.list, uploads.list),
}),
m(downloads.Component),
m(uploads.Component),
view: () => [
m('.widget__heading', [
m('h3', 'File Transfers'),
m(util.SearchBar, {
list: Object.assign({}, downloads.list, uploads.list),
}),
]),
m('.widget__body', [m(downloads.Component), m(uploads.Component)]),
],
};
};
@ -29,14 +31,13 @@ const sections = {
};
const Layout = {
view: (vnode) =>
m('.tab-page', [
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/files/',
}),
m('.file-node-panel', vnode.children),
]),
view: (vnode) => [
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/files/',
}),
m('.node-panel', m('.widget', vnode.children)),
],
};
module.exports = {

View File

@ -4,13 +4,13 @@ const futil = require('files/files_util');
const widget = require('widgets');
let matchString = '';
const reqObj = {};
let currentItem = 0;
const reqObj = {};
async function handleSubmit() {
await rs
.rsJsonApiRequest('/rsFiles/turtleSearch', { matchString })
function handleSubmit() {
rs.rsJsonApiRequest('/rsFiles/turtleSearch', { matchString })
.then((res) => {
// Add prefix to obj keys so that javascript doesn't sort them
reqObj['_' + res.body.retval] = matchString;
currentItem = '_' + res.body.retval;
})
@ -21,16 +21,16 @@ const SearchBar = () => {
return {
view: () =>
m(
'form',
'form.search-form',
{
onsubmit: handleSubmit,
},
[
m('input[type=text][placeholder=search]', {
m('input[type=text][placeholder=search keyword]', {
value: matchString,
oninput: (e) => (matchString = e.target.value),
}),
m('button[type=submit]', 'Submit'),
m('button[type=submit]', m('i.fas.fa-search')),
]
),
};
@ -39,14 +39,12 @@ const SearchBar = () => {
const Layout = () => {
let active = 0;
return {
view: (vnode) =>
m('.widget', [
m('h3', 'Search'),
m('hr'),
m(SearchBar),
view: () => [
m('.widget__heading', [m('h3', 'Search'), m(SearchBar)]),
m('.widget__body', [
m('div.file-search-container', [
m('div.file-search-container__keywords', [
m('h4', 'Keywords'),
m('h5.bold', 'Keywords'),
m(
'div.keywords-container',
Object.keys(reqObj)
@ -69,7 +67,7 @@ const Layout = () => {
]),
m('div.file-search-container__results', [
Object.keys(futil.proxyObj).length === 0
? m('h4', 'Results')
? m('h5.bold', 'Results')
: m('table.results-container', [
m(
'thead.results-header',
@ -96,32 +94,28 @@ const Layout = () => {
'button',
{
onclick: () => {
try {
rs.rsJsonApiRequest(
'/rsFiles/FileRequest',
{
fileName: item.fName,
hash: item.fHash,
flags: futil.RS_FILE_REQ_ANONYMOUS_ROUTING,
size: {
xstr64: item.fSize.xstr64,
},
},
(status) => {
status.retval
? widget.popupMessage([
m('i.fas.fa-file-medical'),
m('h3', 'File is being downloaded!'),
])
: widget.popupMessage([
m('i.fas.fa-file-medical'),
m('h3', 'File is already downloaded!'),
]);
}
);
} catch (error) {
console.log('error in sending download request: ', error);
}
rs.rsJsonApiRequest('/rsFiles/FileRequest', {
fileName: item.fName,
hash: item.fHash,
flags: futil.RS_FILE_REQ_ANONYMOUS_ROUTING,
size: {
xstr64: item.fSize.xstr64,
},
})
.then((res) => {
res.retval
? widget.popupMessage([
m('i.fas.fa-file-medical'),
m('h3', 'File is being downloaded!'),
])
: widget.popupMessage([
m('i.fas.fa-file-medical'),
m('h3', 'File is already downloaded!'),
]);
})
.catch((error) => {
console.log('error in sending download request: ', error);
});
},
},
'Download'
@ -134,6 +128,7 @@ const Layout = () => {
]),
]),
]),
],
};
};

View File

@ -192,39 +192,30 @@ function actionButton(file, action) {
const ProgressBar = () => {
return {
view: (v) =>
m(
'.progressbar',
{
m('.progressbar', [
m('span.progressbar-status', {
style: {
content: v.attrs.rate + '%',
width: v.attrs.rate + '%',
},
},
m(
'span.progress-status',
{
style: {
width: v.attrs.rate + '%',
},
},
v.attrs.rate.toPrecision(3) + '%'
)
),
}),
m('span.progressbar-percent', v.attrs.rate.toPrecision(3) + '%'),
]),
};
};
const chunkStrats = [
'CHUNK_STRATEGY_STREAMING',
'CHUNK_STRATEGY_RANDOM',
'CHUNK_STRATEGY_PROGRESSIVE',
];
const chunkStratsOptions = ['Streaming', 'Random', 'Progressive'];
const chunkStrats = {
0: 'Streaming', // CHUNK_STRATEGY_STREAMING
1: 'Random', // CHUNK_STRATEGY_RANDOM
2: 'Progressive', // CHUNK_STRATEGY_PROGRESSIVE
};
// rstypes.h :: 366
const File = () => {
let chunkStrat;
return {
view: (v) =>
m(
view: (v) => {
chunkStrat = v.attrs && v.attrs.strategy;
return m(
'.file-view',
{
key: v.attrs.info.hash,
@ -233,62 +224,80 @@ const File = () => {
},
},
[
m('p', v.attrs.info.fname),
v.attrs.direction === 'up' || v.attrs.info.downloadStatus === FT_STATE_COMPLETE
? []
: [
actionButton(v.attrs.info, 'cancel'),
actionButton(
v.attrs.info,
v.attrs.info.downloadStatus === FT_STATE_PAUSED ? 'resume' : 'pause'
),
m('.file-view__heading', [
m('h6', v.attrs.info.fname),
!(v.attrs.direction === 'up') && [
m('.file-view__heading-chunk', [
m('label[for=chunkTag]', 'Set Chunk Strategy: '),
m(
'select[id=chunkTag]',
{
value: chunkStrat,
onchange: async (e) => {
chunkStrat = chunkStrats[e.target.selectedIndex];
const res = await rs.rsJsonApiRequest('/rsFiles/setChunkStrategy', {
onchange: (e) => {
chunkStrat = e.target.selectedIndex;
rs.rsJsonApiRequest('/rsFiles/setChunkStrategy', {
hash: v.attrs.info.hash,
newStrategy: chunkStrat,
});
},
},
[chunkStratsOptions.map((opt) => m('option', { value: opt }, opt))]
),
m('label[for=chunkTag]', 'Set Chunk Strategy: '),
],
v.attrs.direction === 'up'
? []
: m(ProgressBar, {
rate: (v.attrs.transferred / v.attrs.info.size.xint64) * 100,
}),
m('span.filestat', m('i.fas.fa-download'), makeFriendlyUnit(v.attrs.transferred)),
m('span.filestat', m('i.fas.fa-file'), makeFriendlyUnit(v.attrs.info.size.xint64)),
m(
'span.filestat',
m('i.fas.fa-arrow-circle-' + v.attrs.direction),
makeFriendlyUnit(v.attrs.info.tfRate * 1024) + '/s'
),
v.attrs.direction === 'up'
? []
: m('span.filestat', { title: 'time remaining' }, [
m('i.fas.fa-clock'),
calcRemainingTime(
v.attrs.info.size.xint64 - v.attrs.transferred,
v.attrs.info.tfRate
[
Object.keys(chunkStrats).map((opt) =>
m('option', { value: opt }, chunkStrats[opt])
),
]
),
]),
m(
'span.filestat',
{ title: 'peers' },
[m('i.fas.fa-users'), v.attrs.info.peers.length],
v.attrs.parts.reduce((a, e) => [...a, ' - ' + makeFriendlyUnit(e)], [])
),
],
]),
m('.file-view__body', [
m(
'.file-view__body-progress',
!(v.attrs.direction === 'up') &&
m(ProgressBar, {
rate: (v.attrs.transferred / v.attrs.info.size.xint64) * 100,
})
),
m('.file-view__body-details', [
m('.file-view__body-details-stat', [
m('span', m('i.fas.fa-download'), makeFriendlyUnit(v.attrs.transferred)),
m('span', m('i.fas.fa-file'), makeFriendlyUnit(v.attrs.info.size.xint64)),
m(
'span',
m('i.fas.fa-arrow-circle-' + v.attrs.direction),
makeFriendlyUnit(v.attrs.info.tfRate * 1024) + '/s'
),
!(v.attrs.direction === 'up') &&
m('span', { title: 'time remaining' }, [
m('i.fas.fa-clock'),
calcRemainingTime(
v.attrs.info.size.xint64 - v.attrs.transferred,
v.attrs.info.tfRate
),
]),
m(
'span',
{ title: 'peers' },
[m('i.fas.fa-users'), v.attrs.info.peers.length],
v.attrs.parts.reduce((a, e) => [...a, ' - ' + makeFriendlyUnit(e)], [])
),
]),
m(
'.file-view__body-details-action',
!(v.attrs.info.downloadStatus === FT_STATE_COMPLETE) && [
actionButton(
v.attrs.info,
v.attrs.info.downloadStatus === FT_STATE_PAUSED ? 'resume' : 'pause'
),
actionButton(v.attrs.info, 'cancel'),
]
),
]),
]),
]
),
);
},
};
};
@ -296,7 +305,7 @@ const SearchBar = () => {
let searchString = '';
return {
view: (v) =>
m('input[type=text][placeholder=SearchDownloads].searchbar', {
m('input[type=text][placeholder=Search].searchbar', {
value: searchString,
oninput: (e) => {
searchString = e.target.value.toLowerCase();

View File

@ -145,15 +145,14 @@ const Layout = () => {
// let root_handle;
let parent;
return {
oninit: async () => {
const res = await rs.rsJsonApiRequest('/rsfiles/requestDirDetails', {
oninit: () => {
rs.rsJsonApiRequest('/rsfiles/requestDirDetails', {
flags: util.RS_FILE_HINTS_REMOTE,
});
parent = res;
}).then((res) => (parent = res));
},
view: (v) => [
m('.widget', [
m('h3', 'Friends Files'),
view: () => [
m('.widget__heading', [m('h3', 'Friends Files')]),
m('.widget__body', [
m(
util.FriendsFilesTable,
m(

View File

@ -21,7 +21,8 @@ function displayfiles() {
class: 'fa-rotate-' + (parStruct.showChild ? '90' : '0'),
style: 'margin-top:12px',
onclick: () => {
if (!loaded) { // if it is not already retrieved
if (!loaded) {
// if it is not already retrieved
parStruct.details.children.map(async (child) => {
const res = await rs.rsJsonApiRequest('/rsfiles/requestDirDetails', {
handle: child.handle.xint64,
@ -43,7 +44,6 @@ function displayfiles() {
position: 'relative',
'--replyDepth': v.attrs.replyDepth,
left: `calc(30px*${v.attrs.replyDepth})`,
},
},
parStruct.details.name
@ -52,7 +52,8 @@ function displayfiles() {
]),
parStruct.showChild &&
childrenList.map((child) =>
m(displayfiles, { // recursive call
m(displayfiles, {
// recursive call
par_directory: { details: child, showChild: false },
replyDepth: v.attrs.replyDepth + 1,
})
@ -65,13 +66,12 @@ const Layout = () => {
// let root_handle;
let parent;
return {
oninit: async () => {
const res = await rs.rsJsonApiRequest('/rsfiles/requestDirDetails', {});
parent = res;
oninit: () => {
rs.rsJsonApiRequest('/rsfiles/requestDirDetails', {}).then((res) => (parent = res));
},
view: (v) => [
m('.widget', [
m('h3', 'My Files'),
view: () => [
m('.widget__heading', [m('h3', 'My Files')]),
m('.widget__body', [
m(
util.MyFilesTable,
m(

View File

@ -123,7 +123,7 @@ const EditThread = () => {
const res = await rs.rsJsonApiRequest('/rsgxsforums/createPost', {
forumId: vnode.attrs.forumId,
mBody: body,
title: title,
title,
authorId: vnode.attrs.authorId,
parentId: vnode.attrs.current_parent,
origPostId: vnode.attrs.current_msgid,
@ -198,14 +198,14 @@ const AddThread = () => {
? await rs.rsJsonApiRequest('/rsgxsforums/createPost', {
forumId: vnode.attrs.forumId,
mBody: body,
title: title,
title,
authorId: identity,
parentId: vnode.attrs.parentId,
})
: await rs.rsJsonApiRequest('/rsgxsforums/createPost', {
forumId: vnode.attrs.forumId,
mBody: body,
title: title,
title,
authorId: identity,
});
@ -479,126 +479,117 @@ const ForumView = () => {
}
});
},
view: (v) =>
view: (v) => [
m(
'.widget',
'a[title=Back]',
{
key: v.attrs.id,
onclick: () =>
m.route.set('/forums/:tab', {
tab: m.route.param().tab,
}),
},
[
m(
'a[title=Back]',
{
onclick: () =>
m.route.set('/forums/:tab', {
tab: m.route.param().tab,
}),
},
m('i.fas.fa-arrow-left')
),
m('i.fas.fa-arrow-left')
),
m('h3', fname),
m(
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsgxsforums/subscribeToForum', {
m('h3', fname),
m(
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsgxsforums/subscribeToForum', {
forumId: v.attrs.id,
subscribe: !fsubscribed,
});
if (res.body.retval) {
fsubscribed = !fsubscribed;
util.Data.DisplayForums[v.attrs.id].isSubscribed = fsubscribed;
}
},
},
fsubscribed ? 'Subscribed' : 'Subscribe'
),
m('[id=forumdetails]', [
m(
'p',
m('b', 'Date created: '),
typeof createDate === 'object'
? new Date(createDate.xint64 * 1000).toLocaleString()
: 'undefined'
),
m('p', m('b', 'Admin: '), fauthor),
m(
'p',
m('b', 'Last activity: '),
typeof lastActivity === 'object'
? new Date(lastActivity.xint64 * 1000).toLocaleString()
: 'undefined'
),
]),
m('hr'),
m('forumdesc', m('b', 'Description: '), util.Data.DisplayForums[v.attrs.id].description),
m('hr'),
m(
'threaddetails',
{
style: 'display:' + (fsubscribed ? 'block' : 'none'),
},
m('h3', 'Threads'),
m(
'button',
{
onclick: () => {
util.popupmessage(
m(AddThread, {
parent_thread: '',
forumId: v.attrs.id,
subscribe: !fsubscribed,
});
if (res.body.retval) {
fsubscribed = !fsubscribed;
util.Data.DisplayForums[v.attrs.id].isSubscribed = fsubscribed;
}
},
authorId: ownId,
parentId: '',
})
);
},
fsubscribed ? 'Subscribed' : 'Subscribe'
),
m('[id=forumdetails]', [
m(
'p',
m('b', 'Date created: '),
typeof createDate === 'object'
? new Date(createDate.xint64 * 1000).toLocaleString()
: 'undefined'
),
m('p', m('b', 'Admin: '), fauthor),
m(
'p',
m('b', 'Last activity: '),
typeof lastActivity === 'object'
? new Date(lastActivity.xint64 * 1000).toLocaleString()
: 'undefined'
),
]),
m('hr'),
m('forumdesc', m('b', 'Description: '), util.Data.DisplayForums[v.attrs.id].description),
m('hr'),
},
['New Thread', m('i.fas.fa-pencil-alt')]
),
m('hr'),
m(
util.ThreadsTable,
m(
'threaddetails',
{
style: 'display:' + (fsubscribed ? 'block' : 'none'),
},
m('h3', 'Threads'),
m(
'button',
{
onclick: () => {
util.popupmessage(
m(AddThread, {
parent_thread: '',
forumId: v.attrs.id,
authorId: ownId,
parentId: '',
})
);
},
},
['New Thread', m('i.fas.fa-pencil-alt')]
),
m('hr'),
m(
util.ThreadsTable,
'tbody',
Object.keys(topThreads).map((key, index) =>
m(
'tbody',
Object.keys(topThreads).map((key, index) =>
'tr',
{
style:
topThreads[key].mMsgStatus === util.THREAD_UNREAD ? { fontWeight: 'bold' } : '',
onclick: () => {
m.route.set('/forums/:tab/:mGroupId/:mMsgId', {
tab: m.route.param().tab,
mGroupId: v.attrs.id,
mMsgId: topThreads[key].mOrigMsgId,
});
},
},
[
m('td', topThreads[key].mMsgName),
m(
'tr',
{
style:
topThreads[key].mMsgStatus === util.THREAD_UNREAD
? { fontWeight: 'bold' }
: '',
onclick: () => {
m.route.set('/forums/:tab/:mGroupId/:mMsgId', {
tab: m.route.param().tab,
mGroupId: v.attrs.id,
mMsgId: topThreads[key].mOrigMsgId,
});
},
},
[
m('td', topThreads[key].mMsgName),
m(
'td',
typeof topThreads[key].mPublishTs === 'object'
? new Date(topThreads[key].mPublishTs.xint64 * 1000).toLocaleString()
: 'undefined'
),
m(
'td',
rs.userList.userMap[topThreads[key].mAuthorId]
? rs.userList.userMap[topThreads[key].mAuthorId]
: 'Unknown'
),
]
)
)
'td',
typeof topThreads[key].mPublishTs === 'object'
? new Date(topThreads[key].mPublishTs.xint64 * 1000).toLocaleString()
: 'undefined'
),
m(
'td',
rs.userList.userMap[topThreads[key].mAuthorId]
? rs.userList.userMap[topThreads[key].mAuthorId]
: 'Unknown'
),
]
)
)
),
]
)
)
),
],
};
};

View File

@ -50,51 +50,49 @@ const Layout = () => {
});
},
view: (vnode) =>
m('.tab-page', [
m(util.SearchBar, {
list: getForums.All,
}),
m(
'button',
{
style: { fontSize: '1.2em', width: '200px' },
onclick: () =>
util.popupmessage(
m(viewUtil.createforum, {
authorId: ownId,
})
),
},
'Create Forum'
),
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/forums/',
}),
m(
'.forums-node-panel',
Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId') // thread's view
? m(viewUtil.ThreadView, {
msgId: vnode.attrs.pathInfo.mMsgId,
forumId: vnode.attrs.pathInfo.mGroupId,
})
: Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId') // Forum's view
? m(viewUtil.ForumView, {
id: vnode.attrs.pathInfo.mGroupId,
})
: m(sections[vnode.attrs.pathInfo.tab], {
list: getForums[vnode.attrs.pathInfo.tab],
})
),
m('.widget', [
m('.top-heading', [
m(
'button',
{
onclick: () =>
ownId &&
util.popupmessage(
m(viewUtil.createforum, {
authorId: ownId,
})
),
},
'Create Forum'
),
m(util.SearchBar, {
list: getForums.All,
}),
]),
Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mMsgId') // thread's view
? m(viewUtil.ThreadView, {
msgId: vnode.attrs.pathInfo.mMsgId,
forumId: vnode.attrs.pathInfo.mGroupId,
})
: Object.prototype.hasOwnProperty.call(vnode.attrs.pathInfo, 'mGroupId') // Forum's view
? m(viewUtil.ForumView, {
id: vnode.attrs.pathInfo.mGroupId,
})
: m(sections[vnode.attrs.pathInfo.tab], {
list: getForums[vnode.attrs.pathInfo.tab],
}),
]),
};
};
module.exports = {
view: (vnode) => {
return m(Layout, {
pathInfo: vnode.attrs,
});
return [
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/forums/',
}),
m('.node-panel', m(Layout, { pathInfo: vnode.attrs })),
];
},
};

View File

@ -86,7 +86,6 @@ async function updatedisplayforums(keyid, details = {}) {
const DisplayForumsFromList = () => {
return {
oninit: (v) => {},
view: (v) =>
m(
'tr',
@ -115,7 +114,6 @@ const ForumSummary = () => {
keyid = v.attrs.details.mGroupId;
updatedisplayforums(keyid);
},
view: (v) => {},
};
};

View File

@ -4,9 +4,8 @@ const util = require('forums/forums_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'My Forums'),
m('hr'),
m('.widget__heading', m('h3', 'My Forums')),
m('.widget__body', [
m(
util.ForumTable,
m('tbody', [

View File

@ -2,7 +2,7 @@ const m = require('mithril');
const Layout = () => {
return {
view: () => [m('.widget', [m('h2', 'Other Forums'), m('hr')])],
view: () => [m('.widget__heading', m('h3', 'Other Forums'))],
};
};

View File

@ -4,9 +4,8 @@ const util = require('forums/forums_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Popular Forums'),
m('hr'),
m('.widget__heading', m('h3', 'Popular Forums')),
m('.widget__body', [
m(
util.ForumTable,
m('tbody', [

View File

@ -4,9 +4,8 @@ const util = require('forums/forums_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Subscribed Forums'),
m('hr'),
m('.widget__heading', m('h3', 'Subscribed Forums')),
m('.widget__body', [
m(
util.ForumTable,
m('tbody', [

View File

@ -2,45 +2,18 @@ const m = require('mithril');
const rs = require('rswebui');
const widget = require('widgets');
const retrosemitext = () => {
return {
view() {
return m(
'.retrotext',
{
style: 'font-weight:500;font-size:2.4rem',
},
[
m(
'span',
{
style: 'color: #3ba4d7',
},
'RETRO'
),
'SHARE',
]
);
},
};
};
const retroshareText = () => {
return {
view() {
return m('.retroshareText', [m(retrosemitext), m('b', 'secure connection for everyone')]);
},
};
};
const logo = () => {
return {
view() {
return m('.logo', [
m('img.logo[width=20%][height=10%]', {
m('img', {
src: '../data/retroshare.svg',
alt: 'retroshare_icon',
}),
m(retroshareText),
m('.retroshareText', [
m('.retrotext', [m('span', 'RETRO'), 'SHARE']),
m('b', 'secure communication for everyone'),
]),
]);
},
};
@ -77,23 +50,18 @@ const webhelp = () => {
widget.popupMessage(m(webhelpConfirm));
},
},
[
m('i.fas .fa-globe-europe', { style: 'color:green' }),
m('p', { style: 'border-width:1px' }, 'Open Web Help'),
]
[m('i.fas.fa-globe-europe'), m('p', 'Open Web Help')]
);
},
};
};
const ConfirmCopied = () => {
return {
view: () => [
m('h3', 'Copied to Clipboard'),
m('hr'),
m(
'p[style="margin: 12px 0 4px"]',
'Your Retroshare ID has been copied to Clipboard.'
),
m('p[style="margin: 12px 0 4px"]', 'Your Retroshare ID has been copied to Clipboard.'),
m(
'p[style="margin: 4px 0 12px"]',
'Now, you can paste and send it to your friend via email or some other way.'
@ -107,17 +75,8 @@ const retroshareId = () => {
return {
view(v) {
return m('.retroshareID', [
m('i.fas .fa-copy', {
style: 'color: #3ba4d7; margin-right: 3px; cursor: pointer',
onclick: () => {
document.getElementById('retroId').select();
document.execCommand('copy');
widget.popupMessage(m(ConfirmCopied));
},
}),
m(
'textarea[readonly] .textArea',
'textarea[readonly].textArea',
{
id: 'retroId',
rows: 1,
@ -129,78 +88,14 @@ const retroshareId = () => {
},
v.attrs.ownCert.substring(31)
),
m('i.fas .fa-share-alt', { style: 'color: #3ba4d7' }),
]);
},
};
};
const Certificate = () => {
let ownCert = '';
function loadOwnCert() {
rs.rsJsonApiRequest(
'/rsPeers/GetShortInvite',
{ formatRadix: true },
(data) => (ownCert = data.invite)
);
}
return {
oninit() {
// Load long cert by default
loadOwnCert();
},
view() {
return m('.certificate ', [
m(logo),
m(
'p',
{
style: 'margin-top:25px;font-size:1.1rem;font-weight:500;',
m('i.fas.fa-copy', {
onclick: () => {
document.getElementById('retroId').select();
document.execCommand('copy');
widget.popupMessage(m(ConfirmCopied));
},
'Open Source cross-platform,'
),
m(
'p',
{
style: 'margin:0;padding:0; margin-top:5px;font-size:1.1rem;',
},
'private and secure decentralized communication platform'
),
m(
'p',
{
style: 'margin-top:80px;color: #3ba4d7;font-size:1.1rem;font-weight:600;',
},
'This is your Retroshare ID. Copy and share with your friends!'
),
m(retroshareId, { ownCert }),
m(
'p',
{
style: 'margin-bottom:5px;margin-top:40px;font-size:1.1rem',
},
'Did you receive a Retroshare ID from your friend ?'
),
m(
'button',
{
onclick: () => {
widget.popupMessage(m(AddFriend));
},
},
'Add Friend'
),
m(
'p',
{
style: 'margin-bottom:5px;margin-top:40px;font-size:1.1rem',
},
'Do you need help with Retoshare ?'
),
m(webhelp),
}),
m('i.fas.fa-share-alt'),
]);
},
};
@ -224,52 +119,52 @@ function confirmAddPrompt(details, cert, long) {
long
? m(
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsPeers/loadCertificateFromString', { cert });
if (res.body.retval) {
widget.popupMessage([
m('h3', 'Successful'),
m('hr'),
m('p', 'Successfully added friend.'),
]);
} else {
widget.popupMessage([
m('h3', 'Error'),
m('hr'),
m('p', 'An error occoured during adding. Friend not added.'),
]);
}
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsPeers/loadCertificateFromString', { cert });
if (res.body.retval) {
widget.popupMessage([
m('h3', 'Successful'),
m('hr'),
m('p', 'Successfully added friend.'),
]);
} else {
widget.popupMessage([
m('h3', 'Error'),
m('hr'),
m('p', 'An error occoured during adding. Friend not added.'),
]);
}
},
},
},
'Finish'
)
'Finish'
)
: m(
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsPeers/addSslOnlyFriend', {
sslId: details.id,
pgpId: details.gpg_id,
});
if (res.body.retval) {
widget.popupMessage([
m('h3', 'Successful'),
m('hr'),
m('p', 'Successfully added friend.'),
]);
} else {
widget.popupMessage([
m('h3', 'Error'),
m('hr'),
m('p', 'An error occoured during adding. Friend not added.'),
]);
}
'button',
{
onclick: async () => {
const res = await rs.rsJsonApiRequest('/rsPeers/addSslOnlyFriend', {
sslId: details.id,
pgpId: details.gpg_id,
});
if (res.body.retval) {
widget.popupMessage([
m('h3', 'Successful'),
m('hr'),
m('p', 'Successfully added friend.'),
]);
} else {
widget.popupMessage([
m('h3', 'Error'),
m('hr'),
m('p', 'An error occoured during adding. Friend not added.'),
]);
}
},
},
},
'Finish'
),
'Finish'
),
]);
}
@ -311,10 +206,7 @@ const AddFriend = () => {
view: (vnode) =>
m('.widget', [
m('h3', 'Add friend'),
m(
'p',
'Did you recieve a certificate from a friend?'
),
m('h5', 'Did you recieve a certificate from a friend?'),
m('hr'),
m(
'.cert-drop-zone',
@ -324,11 +216,7 @@ const AddFriend = () => {
ondragexit: () => (vnode.state.isDragged = false),
// Styling element when file is dragged
style: vnode.state.isDragged
? {
border: '5px solid #3ba4d7',
}
: {},
style: { border: vnode.state.isDragged && '5px solid #3ba4d7' },
ondragover: (e) => e.preventDefault(),
ondrop: (e) => {
@ -339,7 +227,10 @@ const AddFriend = () => {
},
[
m('p[style="margin: 16px 0 4px; font-size: 12px;"]', 'You can directly upload or Drag and drop the file below'),
m(
'p[style="margin: 16px 0 4px"]',
'You can directly upload or Drag and drop the file below'
),
m('input[type=file][name=certificate]', {
onchange: (e) => {
// Note: this one is for the 'browse' button
@ -347,10 +238,13 @@ const AddFriend = () => {
},
}),
m('p[style="width: 100%; text-align: center; margin: 5px 0;"]', 'OR'),
m('textarea[rows=5][placeholder="Paste the certificate here"][style="width: 100%; display: block; resize: vertical;"]', {
oninput: (e) => (certificate = e.target.value),
value: certificate,
}),
m(
'textarea[rows=5][placeholder="Paste the certificate here"][style="width: 100%; display: block; resize: vertical;"]',
{
oninput: (e) => (certificate = e.target.value),
value: certificate,
}
),
m(
'button[style="margin-top: 10px;"]',
{
@ -364,9 +258,60 @@ const AddFriend = () => {
};
};
const Certificate = () => {
let ownCert = '';
function loadOwnCert() {
rs.rsJsonApiRequest(
'/rsPeers/GetShortInvite',
{ formatRadix: true },
(data) => (ownCert = data.invite)
);
}
return {
oninit() {
// Load long cert by default
loadOwnCert();
},
view() {
return m('.homepage ', [
m(logo),
m('.certificate', [
m('.certificate__heading', [
m('h1', 'Welcome to Web Interface of Retroshare!'),
'Retroshare is an Open Source Cross-platform,',
m('br'),
'Private and Secure Decentralized Communication Platform.',
]),
m('.certificate__content', [
m('.rsId', [
m('p', 'This is your Retroshare ID. Copy and share with your friends!'),
m(retroshareId, { ownCert }),
]),
m('.add-friend', [
m('h6', 'Did you receive a Retroshare ID from your friend ?'),
m(
'button',
{
onclick: () => {
widget.popupMessage(m(AddFriend));
},
},
'Add Friend'
),
]),
m('.webhelp-container', [m('h6', 'Do you need help with Retoshare ?'), m(webhelp)]),
]),
]),
]);
},
};
};
const Layout = () => {
return {
view: () => m('.tab-page ', [m(Certificate)]),
view: () => m(Certificate),
};
};

View File

@ -20,29 +20,28 @@ const Layout = () => {
});
},
view: (v) => [
m('.widget', [
m('div.msg-attachment-container', [
m('h3', 'Attachments'),
m('.view-toggle', [
m(
'.mail-view',
{
onclick: () => (viewChanged = false),
style: { backgroundColor: viewChanged ? '#fff' : '#019DFF' },
},
m('i.fas.fa-mail-bulk')
),
m(
'.attachment-view',
{
onclick: () => (viewChanged = true),
style: { backgroundColor: viewChanged ? '#019DFF' : '#fff' },
},
m('i.fas.fa-file')
),
]),
m('.widget__heading', [
m('h3', 'Attachments'),
m('.view-toggle', [
m(
'.mail-view',
{
onclick: () => (viewChanged = false),
style: { backgroundColor: viewChanged ? '#fff' : '#019DFF' },
},
m('i.fas.fa-mail-bulk')
),
m(
'.attachment-view',
{
onclick: () => (viewChanged = true),
style: { backgroundColor: viewChanged ? '#019DFF' : '#fff' },
},
m('i.fas.fa-file')
),
]),
m('hr'),
]),
m('.widget__body', [
viewChanged
? m(util.AttachmentSection, {
files,

View File

@ -5,9 +5,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Drafts'),
m('hr'),
m('.widget__heading', m('h3', 'Draft')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Important'),
m('hr'),
m('.widget__heading', m('h3', 'Important')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Inbox'),
m('hr'),
m('.widget__heading', m('h3', 'Inbox')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Later'),
m('hr'),
m('.widget__heading', m('h3', 'Later')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Outbox'),
m('hr'),
m('.widget__heading', m('h3', 'Outbox')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Personal'),
m('hr'),
m('.widget__heading', m('h3', 'Personal')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -1,7 +1,6 @@
const m = require('mithril');
const rs = require('rswebui');
const util = require('mail/mail_util');
const widget = require('widgets');
const peopleUtil = require('people/people_util');
const compose = require('mail/mail_compose');
@ -116,9 +115,9 @@ const Layout = {
};
return [
m('.tab-page', [
m('.side-bar', [
m(
'button[id=composebtn]',
'button.mail-compose-btn',
{
onclick: () =>
composeData.allUsers &&
@ -129,19 +128,6 @@ const Layout = {
},
'Compose'
),
m(
'select[id=tags]',
{
value: tagselect.showval,
onchange: (e) => {
tagselect.showval = tagselect.opts[e.target.selectedIndex];
},
},
[tagselect.opts.map((o) => m('option', { value: o }, o.toLocaleString()))]
),
m(util.SearchBar, {
list: {},
}),
m(util.Sidebar, {
tabs: Object.keys(sections),
size: sectionsSize,
@ -152,8 +138,28 @@ const Layout = {
size: sectionsquickviewSize,
baseRoute: '/mail/',
}),
m('.mail-node-panel', vnode.children),
]),
m(
'.node-panel',
m('.widget', [
m('.top-heading', [
m(
'select.mail-tag',
{
value: tagselect.showval,
onchange: (e) => {
tagselect.showval = tagselect.opts[e.target.selectedIndex];
},
},
[tagselect.opts.map((o) => m('option', { value: o }, o.toLocaleString()))]
),
m(util.SearchBar, {
list: {},
}),
]),
vnode.children,
])
),
];
},
};

View File

@ -5,9 +5,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Sent'),
m('hr'),
m('.widget__heading', m('h3', 'Sent')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Spam'),
m('hr'),
m('.widget__heading', m('h3', 'Spam')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Starred'),
m('hr'),
m('.widget__heading', m('h3', 'Starred')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'System'),
m('hr'),
m('.widget__heading', m('h3', 'System')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Todo'),
m('hr'),
m('.widget__heading', m('h3', 'Todo')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Trash'),
m('hr'),
m('.widget__heading', m('h3', 'Trash')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -237,145 +237,163 @@ const MessageView = () => {
(data) => (details = { ...details, avatar: data.details.mAvatar })
);
},
view: (v) =>
view: () =>
m(
'.widget.msgview',
'.msg-view',
{
key: details.msgId,
},
[
m(
'a[title=Back]',
{
onclick: () =>
m.route.set('/mail/:tab', {
tab: m.route.param().tab,
}),
},
m('i.fas.fa-arrow-left')
),
m('h3', details.title),
m('.msgHeader', [
details.from &&
m(peopleUtil.UserAvatar, {
avatar: details.avatar,
firstLetter: rs.userList.userMap[details.from._addr_string]
? rs.userList.userMap[details.from._addr_string].slice(0, 1).toUpperCase()
: '',
}),
m('.msgHeaderDetails', [
details.from &&
m('from', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'From: '),
rs.userList.userMap[details.from._addr_string],
]),
toList &&
Object.keys(toList).length > 0 &&
// TODO: optimize javascript for show-more and show-less working
m('to', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'To: '),
m(
'div.truncate[id=truncate]',
Object.keys(toList).map((key, index) => m('p', rs.userList.userMap[key] + ', '))
),
m(
'button[id=show-more]',
{
style: {
display: Object.keys(toList).length > 10 ? 'block' : 'none',
},
onclick: () => {
document.querySelector('#show-more').style.display = 'none';
document.querySelector('#truncate').style.height = 'max-content';
document.querySelector('#show-less').style.display = 'block';
},
},
'Show More'
),
m(
'button[id=show-less][style="display: none;"]',
{
onclick: () => {
document.querySelector('#show-more').style.display = 'block';
document.querySelector('#truncate').style.height = '22px';
document.querySelector('#show-less').style.display = 'none';
},
},
'Show Less'
),
]),
ccList &&
Object.keys(ccList).length > 0 &&
m('cc', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'CC: '),
Object.keys(ccList).map((key, index) => m('p', rs.userList.userMap[key] + ', ')),
]),
bccList &&
Object.keys(bccList).length > 0 &&
m('bcc', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'BCC: '),
Object.keys(bccList).map((key, index) => m('p', rs.userList.userMap[key] + ', ')),
]),
m('.msg-view-nav', [
m(
'a[title=Back]',
{
onclick: () =>
m.route.set('/mail/:tab', {
tab: m.route.param().tab,
}),
},
m('i.fas.fa-arrow-left')
),
m('.msg-view-nav__action', [
m('button', 'Reply'),
m('button', 'Reply All'),
m('button', 'Forward'),
m(
'button',
{
onclick: () =>
widget.popupMessage([
m('p', 'Are you sure you want to delete this mail?'),
m(
'button',
{
onclick: async () => {
rs.rsJsonApiRequest('/rsMsgs/MessageToTrash', {
msgId: details.msgId,
bTrash: true,
});
const res = await rs.rsJsonApiRequest('/rsMsgs/MessageDelete', {
msgId: details.msgId,
});
res.body.retval
? widget.popupMessage([
m('h3', 'Success'),
m('hr'),
m('p', 'Mail Deleted.'),
])
: widget.popupMessage([
m('h3', 'Error'),
m('hr'),
m('p', res.body.errorMessage),
]);
m.redraw();
m.route.set('/mail/:tab', {
tab: m.route.param().tab,
});
},
},
'Delete'
),
]),
},
'Delete'
),
]),
]),
m('button', 'Reply'),
m('button', 'Reply All'),
m('button', 'Forward'),
m(
'button',
{
onclick: () =>
widget.popupMessage([
m('p', 'Are you sure you want to delete this mail?'),
m(
'button',
{
onclick: async () => {
rs.rsJsonApiRequest('/rsMsgs/MessageToTrash', {
msgId: details.msgId,
bTrash: true,
});
const res = await rs.rsJsonApiRequest('/rsMsgs/MessageDelete', {
msgId: details.msgId,
});
res.body.retval
? widget.popupMessage([
m('h3', 'Success'),
m('hr'),
m('p', 'Mail Deleted.'),
])
: widget.popupMessage([
m('h3', 'Error'),
m('hr'),
m('p', res.body.errorMessage),
]);
m.redraw();
m.route.set('/mail/:tab', {
tab: m.route.param().tab,
});
m('.msg-view__header', [
m('h3', details.title),
m('.msg-details', [
details.from &&
m(peopleUtil.UserAvatar, {
avatar: details.avatar,
firstLetter: rs.userList.userMap[details.from._addr_string]
? rs.userList.userMap[details.from._addr_string].slice(0, 1).toUpperCase()
: '',
}),
m('.msg-details__info', [
details.from &&
m('.msg-details__info-item', [
m('b', 'From: '),
rs.userList.userMap[details.from._addr_string] || 'Unknown',
]),
toList &&
Object.keys(toList).length > 0 &&
// TODO: optimize javascript for show-more and show-less working
m('.msg-details__info-item', [
m('b', 'To: '),
m(
'#truncate',
Object.keys(toList).map((key, index) =>
m('span', `${rs.userList.userMap[key]}, `)
)
),
m(
'button[id=show-more]',
{
style: {
display: Object.keys(toList).length > 10 ? 'block' : 'none',
},
onclick: () => {
document.querySelector('#show-more').style.display = 'none';
document.querySelector('#truncate').style.height = '6rem';
document.querySelector('#truncate').style.overflow = 'auto';
document.querySelector('#show-less').style.display = 'block';
},
},
},
'Delete'
),
]),
},
'Delete'
),
m('hr'),
'...'
),
m(
'button[id=show-less][style="display: none;"]',
{
onclick: () => {
document.querySelector('#show-more').style.display = 'block';
document.querySelector('#truncate').style.height = '1.75rem';
document.querySelector('#truncate').style.overflow = 'hidden';
document.querySelector('#show-less').style.display = 'none';
},
},
'less'
),
]),
ccList &&
Object.keys(ccList).length > 0 &&
m('.msg-details__info-item', [
m('b', 'CC: '),
Object.keys(ccList).map((key, index) =>
m('p', `${rs.userList.userMap[key]}, `)
),
]),
bccList &&
Object.keys(bccList).length > 0 &&
m('.msg-details__info-item', [
m('b', 'BCC: '),
Object.keys(bccList).map((key, index) =>
m('p', `${rs.userList.userMap[key]}, `)
),
]),
]),
]),
]),
m(
'iframe[title=message].msg',
{
srcdoc: message,
},
message
'.msg-view__body',
m(
'iframe[title=message]',
{
srcdoc: message,
},
message
)
),
files.length > 0 && [
m('hr'),
m('h3', 'Attachments'),
m(AttachmentSection, {
files,
}),
],
files.length > 0 &&
m('.msg-view__attachment', [
m('h3', 'Attachments'),
m('.msg-view__attachment-items', [
m(AttachmentSection, {
files,
}),
]),
]),
]
),
};
@ -401,7 +419,7 @@ const SearchBar = () => {
let searchString = '';
return {
view: (v) =>
m('input[type=text][id=searchmail][placeholder=Search Subject].searchbar', {
m('input[type=text][placeholder=Search Subject].searchbar', {
value: searchString,
oninput: (e) => {
searchString = e.target.value.toLowerCase();
@ -467,12 +485,11 @@ const Sidebar = () => {
const SidebarQuickView = () => {
// for the Mail tab, to be moved later.
let quickactive = -1;
return {
view: (v) =>
m(
'.sidebarquickview',
m('h4', 'Quick View'),
m('h6.bold', 'Quick View'),
v.attrs.tabs.map((panelName, index) =>
m(
m.route.Link,

View File

@ -4,9 +4,8 @@ const util = require('mail/mail_util');
const Layout = () => {
return {
view: (v) => [
m('.widget', [
m('h3', 'Work'),
m('hr'),
m('.widget__heading', m('h3', 'Work')),
m('.widget__body', [
m(
util.Table,
m(

View File

@ -40,7 +40,7 @@ const navbar = () => {
src: '../data/retroshare.svg',
alt: 'retroshare_icon',
}),
m('h4', 'Retroshare'),
m('h5', 'Retroshare'),
]),
m('.nav-menu__box', [
Object.keys(vnode.attrs.links).map((linkName, i) => {
@ -51,7 +51,7 @@ const navbar = () => {
href: vnode.attrs.links[linkName],
class: 'item' + (active ? ' item-selected' : ''),
},
[navIcon[linkName], m('p[style="margin: 0; align-self: end"]', linkName)]
[navIcon[linkName], m('p', linkName)]
);
}),
m(
@ -85,7 +85,7 @@ const Layout = () => {
config: '/config/network',
},
}),
m('#tab-content', vnode.children),
m('.tab-content', vnode.children),
]),
};
};

View File

@ -125,24 +125,24 @@ const FriendsList = () => {
},
view: () =>
m('.widget', [
m('h3', 'Friend nodes'),
m('hr'),
Object.entries(Data.gpgDetails)
.sort((a, b) => {
return a[1].isOnline === b[1].isOnline ? 0 : a[1].isOnline ? -1 : 1;
})
.map((item) => {
const id = item[0];
return m(Friend, { id });
}),
m('.widget__heading', [m('h3', 'Friend nodes'), m(SearchBar)]),
m('.widget__body', [
Object.entries(Data.gpgDetails)
.sort((a, b) => {
return a[1].isOnline === b[1].isOnline ? 0 : a[1].isOnline ? -1 : 1;
})
.map((item) => {
const id = item[0];
return m(Friend, { id });
}),
]),
]),
};
};
const Layout = () => {
return {
view: () => m('.tab-page', [m(SearchBar), m(FriendsList)]),
view: () => m('.node-panel', m(FriendsList)),
};
};

View File

@ -8,20 +8,18 @@ const AllContacts = () => {
return {
view: () => {
return m('.widget', [
m('h3', 'Contacts', m('span.counter', list.length)),
m('hr'),
list.map((id) => m(peopleUtil.regularcontactInfo, { id })),
m('.widget__heading', [
m('h3', 'Contacts', m('span.counter', list.length)),
m(peopleUtil.SearchBar),
]),
m('.widget__body', [list.map((id) => m(peopleUtil.regularcontactInfo, { id }))]),
]);
},
};
};
const Layout = {
view: (vnode) => m('.tab-page', [m(peopleUtil.SearchBar), m(AllContacts)]),
};
module.exports = {
view: (vnode) => {
return m(Layout);
view: () => {
return m(AllContacts);
},
};

View File

@ -7,20 +7,18 @@ const MyContacts = () => {
return {
view: () => {
return m('.widget', [
m('h3', 'MyContacts', m('span.counter', list.length)),
m('hr'),
list.map((id) => m(peopleUtil.regularcontactInfo, { id })),
m('.widget__heading', [
m('h3', 'MyContacts', m('span.counter', list.length)),
m(peopleUtil.SearchBar),
]),
m('.widget__body', [list.map((id) => m(peopleUtil.regularcontactInfo, { id }))]),
]);
},
};
};
const Layout = {
view: (vnode) => m('.tab-page', [m(peopleUtil.SearchBar), m(MyContacts)]),
};
module.exports = {
view: (vnode) => {
return m(Layout);
view: () => {
return m(MyContacts);
},
};

View File

@ -29,26 +29,26 @@ const SignedIdentiy = () => {
owns.ids.length > 0
? rs.rsJsonApiRequest(
'/rsIdentity/createIdentity',
{
id: owns.ids[0],
name: v.attrs.name,
pseudonimous: false,
pgpPassword: passphase,
},
(data) => {
const message = data.retval
? 'Successfully created identity.'
: 'An error occured while creating identity.';
console.log(message);
widget.popupMessage([m('h3', 'Create new Identity'), m('hr'), message]);
}
)
'/rsIdentity/createIdentity',
{
id: owns.ids[0],
name: v.attrs.name,
pseudonimous: false,
pgpPassword: passphase,
},
(data) => {
const message = data.retval
? 'Successfully created identity.'
: 'An error occured while creating identity.';
console.log(message);
widget.popupMessage([m('h3', 'Create new Identity'), m('hr'), message]);
}
)
: widget.popupMessage([
m('h3', 'Create new Identity'),
m('hr'),
'An error occured while creating identity.',
]);
m('h3', 'Create new Identity'),
m('hr'),
'An error occured while creating identity.',
]);
});
},
},
@ -99,10 +99,10 @@ const CreateIdentity = () => {
m(
'p',
'You can have one or more identities. ' +
'They are used when you chat in lobbies, ' +
'forums and channel comments. ' +
'They act as the destination for distant chat and ' +
'the Retroshare distant mail system.'
'They are used when you chat in lobbies, ' +
'forums and channel comments. ' +
'They act as the destination for distant chat and ' +
'the Retroshare distant mail system.'
),
m(
'button',
@ -111,18 +111,18 @@ const CreateIdentity = () => {
!pseudonimous
? widget.popupMessage(m(SignedIdentiy, { name }))
: rs.rsJsonApiRequest(
'/rsIdentity/createIdentity',
{
name,
pseudonimous,
},
(data) => {
const message = data.retval
? 'Successfully created identity.'
: 'An error occured while creating identity.';
widget.popupMessage([m('h3', 'Create new Identity'), m('hr'), message]);
}
);
'/rsIdentity/createIdentity',
{
name,
pseudonimous,
},
(data) => {
const message = data.retval
? 'Successfully created identity.'
: 'An error occured while creating identity.';
widget.popupMessage([m('h3', 'Create new Identity'), m('hr'), message]);
}
);
},
},
'Create'
@ -192,28 +192,28 @@ const EditIdentity = () => {
onclick: () => {
!peopleUtil.checksudo(v.attrs.details.mPgpId)
? widget.popupMessage([
m(SignedEditIdentity, {
name,
details: v.attrs.details,
}),
])
m(SignedEditIdentity, {
name,
details: v.attrs.details,
}),
])
: rs.rsJsonApiRequest(
'/rsIdentity/updateIdentity',
{
id: v.attrs.details.mId,
'/rsIdentity/updateIdentity',
{
id: v.attrs.details.mId,
name,
name,
// avatar: v.attrs.details.mAvatar.mData.base64,
pseudonimous: true,
},
(data) => {
const message = data.retval
? 'Successfully Updated identity.'
: 'An error occured while updating identity.';
widget.popupMessage([m('h3', 'Update Identity'), m('hr'), message]);
}
);
// avatar: v.attrs.details.mAvatar.mData.base64,
pseudonimous: true,
},
(data) => {
const message = data.retval
? 'Successfully Updated identity.'
: 'An error occured while updating identity.';
widget.popupMessage([m('h3', 'Update Identity'), m('hr'), message]);
}
);
},
},
'Save'
@ -277,7 +277,10 @@ const Identity = () => {
[
m('h4', details.mNickname),
details.mNickname &&
m(peopleUtil.UserAvatar, { avatar: details.mAvatar, firstLetter: details.mNickname.slice(0, 1).toUpperCase() }),
m(peopleUtil.UserAvatar, {
avatar: details.mAvatar,
firstLetter: details.mNickname.slice(0, 1).toUpperCase(),
}),
m('.details', [
m('p', 'ID:'),
m('p', details.mId),
@ -336,21 +339,17 @@ const Layout = () => {
oninit: () => peopleUtil.ownIds((data) => (ownIds = data)),
view: () =>
m('.widget', [
m('h3', 'Own Identities', m('span.counter', ownIds.length)),
m('hr'),
m(
'button',
{
onclick: () => widget.popupMessage(m(CreateIdentity)),
},
'New Identity'
),
ownIds.map((id) =>
m(Identity, {
id,
})
),
m('.widget__heading', [
m('h3', 'Own Identities', m('span.counter', ownIds.length)),
m(
'button',
{
onclick: () => widget.popupMessage(m(CreateIdentity)),
},
'New Identity'
),
]),
m('.widget__body', [ownIds.map((id) => m(Identity, { id }))]),
]),
};
};

View File

@ -8,14 +8,13 @@ const sections = {
};
const Layout = {
view: (vnode) =>
m('.tab-page', [
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/people/',
}),
m('.node-panel .', vnode.children),
]),
view: (vnode) => [
m(widget.Sidebar, {
tabs: Object.keys(sections),
baseRoute: '/people/',
}),
m('.node-panel .', vnode.children),
],
};
module.exports = {

View File

@ -0,0 +1,21 @@
//---------------------------------- Colors ----------------------------------//
/// Primary Retro color
$primary-retro-color: #118fcc !default;
/// Primary color
$primary-color: #019dff !default;
/// Primary light color
$primary-light-color: #9bdaff !default;
/// Light red
$red-color: #ff3a4a !default;
/// Dark
$dark-color: #14141b !default;
/// Light
$light-color: #eef3f6 !default;
/// Message Starred Color
$golden-yellow-color: #fcba03;

View File

@ -1,3 +1,5 @@
@forward "variables";
@forward "mixins";
@forward "functions";
@forward 'variables';
@forward 'colors';
@forward 'mixins';
@forward 'functions';
@forward 'typography';

View File

@ -4,10 +4,12 @@
/// Button Mixin
@mixin button($bg-color) {
width: max-content;
height: max-content;
color: white;
background: $bg-color;
font-size: 1.2em;
padding: 5px 10px;
font-size: 1rem;
padding: 0.4rem 1rem;
border: 0;
border-radius: 5px;
cursor: pointer;

View File

@ -0,0 +1,46 @@
//-------------------------------- Typography --------------------------------//
h1 {
font-size: 3rem;
}
h2 {
font-size: 2.25rem;
}
h3 {
font-size: 1.875rem;
}
h4 {
font-size: 1.5rem;
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1.125rem;
}
p {
font-size: 1rem;
}
.small {
font-size: 0.875rem;
}
.bold {
font-weight: bold;
}
h1,
h2,
h3,
h4,
h5,
h6,
p {
font-weight: normal;
}

View File

@ -1,22 +1,3 @@
// -----------------------------------------------------------------------------
// This file contains all application-wide Sass variables.
// -----------------------------------------------------------------------------
//---------------------------------- Colors ----------------------------------//
/// Primary color
$primary-color: #019dff !default;
/// Primary light color
$primary-light-color: #9bdaff !default;
/// Light red
$red-color: #ff3a4a !default;
/// Dark
$dark-color: #14141b !default;
/// Light
$light-color: #eef3f6 !default;
/// Message Starred Color
$golden-yellow-color: #fcba03;

View File

@ -1,6 +1,7 @@
/******************************
General site-wide rules
******************************/
@use '../abstracts/colors' as *;
#main {
height: 100vh;
@ -9,19 +10,19 @@ General site-wide rules
/* Main base div for tabs used by m.route */
.content {
height: 100%;
display: flex;
overflow: hidden;
}
/* Main tab content */
#tab-content {
.tab-content {
height: 100%;
background-color: #eef3f6;
width: 100%;
display: flex;
background-color: $light-color;
animation: fadein 0.3s;
overflow: auto;
}
/* Individual tab pages */
.tab-page {
animation: fadein 0.5s;
}
input[type='text'],
input[type='password'],
@ -34,25 +35,29 @@ textarea {
font-weight: 400;
border: 1px solid #ccc;
border-radius: 5px;
padding: 0.5rem;
padding: 0.4rem 0.8rem;
/* Disable chromium's focused element hinting*/
outline: transparent;
}
input:focus {
border: 1px solid #3ba4d7;
box-shadow: inset 0 0 5px #ccc;
input {
&:focus {
border: 1px solid #3ba4d7;
box-shadow: inset 0 0 5px #ccc;
}
&.stretched {
width: 90%;
}
&.small {
max-width: 70%;
padding: 0.1rem;
}
&.searchbar {
width: 40%;
}
}
input.stretched {
width: 90%;
}
input.small {
max-width: 70%;
font-size: 1em;
padding: 0.1em;
}
input.searchbar {
display: block;
margin: 0.9em 0 0 0.9em;
a {
cursor: pointer;
}
table {
@ -62,21 +67,18 @@ table {
border-collapse: collapse;
text-align: center;
color: #333;
font-size: 1.2em;
}
table th {
font-weight: 100;
font-size: 1.3em;
color: black;
border-bottom: 2px solid #eee;
}
table tr {
border-bottom: 1px solid #eee;
font-size: 1.125rem;
& th {
font-size: 1.125rem;
color: black;
border-bottom: 2px solid #eee;
}
& tr {
border-bottom: 1px solid #eee;
}
}
h3 {
font-size: 2em;
font-weight: 100;
color: #444;
}
hr {
@ -89,9 +91,9 @@ hr {
grid-template-columns: auto auto;
gap: 1rem;
justify-content: start;
}
.grid-2col input[type='checkbox'] {
margin-top: 20px;
& input[type='checkbox'] {
margin-top: 20px;
}
}
.error {

View File

@ -1,5 +1,5 @@
html {
font-size: 100%;
font-size: 14px;
box-sizing: border-box;
}
@ -16,6 +16,8 @@ h1,
h2,
h3,
h4,
h5,
h6,
p,
figure,
blockquote,
@ -26,8 +28,8 @@ dd {
}
/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
ul[role="list"],
ol[role="list"] {
ul[role='list'],
ol[role='list'] {
list-style: none;
}
@ -66,7 +68,7 @@ select {
/* Remove all animations and transitions for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
html:focus-within {
scroll-behavior: auto;
scroll-behavior: auto;
}
*,
*::before,

View File

@ -1,3 +1,5 @@
@forward "buttons";
@forward "navbar";
@forward "progress-bar";
@forward 'buttons';
@forward 'media';
@forward 'navbar';
@forward 'posts';
@forward 'progress-bar';

View File

@ -0,0 +1,22 @@
@use '../abstracts/colors' as *;
.media-item {
display: flex;
margin-top: 0.5rem;
padding: 1rem;
border: 1px solid transparentize($dark-color, 0.9);
border-radius: 4px;
&__details {
flex-basis: 40%;
display: flex;
align-items: start;
gap: 0.5rem;
& img {
width: 6rem;
object-fit: contain;
}
}
&__desc {
flex-basis: 60%;
}
}

View File

@ -1,4 +1,4 @@
@use '../abstracts/' as *;
@use '../abstracts/colors' as *;
/* Navbar */
.nav-menu {
@ -13,7 +13,6 @@
margin-right: 0rem;
&__logo {
width: 130px;
padding: 1.2rem 0;
display: flex;
gap: 0.3rem;
@ -24,9 +23,9 @@
width: 1.6rem;
}
h4 {
h5 {
line-height: 1;
color: white;
align-self: end;
}
}
@ -42,6 +41,7 @@
display: flex;
align-items: center;
overflow: hidden;
line-height: 1;
&:hover {
background-color: transparentize($light-color, 0.85);
@ -97,6 +97,7 @@
display: flex;
}
}
a.item {
margin: 4px;
padding: 10px;
@ -104,66 +105,59 @@ a.item {
text-decoration: none;
color: #ccc;
font-size: 0.875em;
/* CSS capitalization is magical! */
text-transform: capitalize;
transition: all 300ms;
/* To vertically stack child nodes */
transition: 300ms;
display: inline-flex;
flex-direction: row;
}
.sidebar {
height: 30%;
width: 200px;
background-color: white;
}
.sidebar a {
text-decoration: none;
text-transform: capitalize;
padding: 1em;
cursor: pointer;
display: block;
font-size: 0.95em;
color: #999;
}
.sidebar a:hover {
color: #222;
}
.sidebar .selected-sidebar-link {
font-weight: bold;
color: #222;
border-left: 5px solid #3ba4d7;
animation: expand-left-border 0.1s;
& a {
text-decoration: none;
text-transform: capitalize;
padding: 1em;
cursor: pointer;
display: block;
font-size: 0.95em;
color: #999;
&:hover {
color: #222;
}
}
& .selected-sidebar-link {
font-weight: bold;
color: #222;
border-left: 5px solid #3ba4d7;
animation: expand-left-border 0.1s;
}
}
.sidebarquickview {
height: 30%;
width: 200px;
top: 300px;
background-color: white;
}
.sidebarquickview a {
text-decoration: none;
text-transform: capitalize;
padding: 1em;
cursor: pointer;
display: block;
font-size: 0.95em;
color: #999;
}
.sidebarquickview a:hover {
color: #222;
}
.sidebarquickview .selected-sidebarquickview-link {
font-weight: bold;
color: #222;
border-left: 5px solid #3ba4d7;
animation: expand-left-border 0.1s;
& > h6 {
padding: 0.5rem;
}
& a {
text-decoration: none;
text-transform: capitalize;
padding: 0.5rem 1rem;
display: block;
color: #999;
& a:hover {
color: #222;
}
}
& .selected-sidebarquickview-link {
font-weight: bold;
color: #222;
border-left: 5px solid #3ba4d7;
animation: expand-left-border 0.1s;
}
}
/* Content adjacent to sidebar */
.node-panel {
position: relative;
bottom: 155px;
margin-left: 200px;
width: 100%;
padding: 0.5rem;
animation: fadein 0.5s;
}

View File

@ -0,0 +1,41 @@
@use '../abstracts/colors' as *;
.posts {
height: 100%;
margin-top: 1rem;
flex-direction: column;
overflow: auto;
&__heading {
display: flex;
justify-content: space-between;
}
&-container {
height: 100%;
padding: 1rem;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 2rem;
border: 1px solid transparentize($dark-color, 0.9);
border-radius: 4px;
overflow: auto;
&-card {
min-height: 240px;
flex-direction: column;
border: 1px solid transparentize($dark-color, 0.5);
border-radius: 4px;
cursor: pointer;
text-align: center;
& img {
flex-basis: 90%;
object-fit: cover;
}
& p {
padding: 0 0.125rem;
flex-basis: 10%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}

View File

@ -1,23 +1,26 @@
@use '../abstracts/colors' as *;
.progressbar {
width: 100%;
border-radius: 500px;
background-color: #eef3f6;
height: 2rem;
position: relative;
text-align: left;
}
.progressbar:before {
position: absolute;
text-align: center;
left: 0;
right: 0;
background-color: $light-color;
border-radius: 20px;
overflow: hidden;
&-status {
position: absolute;
top: 0;
left: 0;
height: 100%;
color: $dark-color;
background-color: $primary-color;
}
&-percent {
position: absolute;
inset: 0;
margin: auto;
width: fit-content;
height: fit-content;
}
}
.progress-status {
display: inline-block;
height: 100%;
padding: 5px;
border-radius: 500px;
color: #000;
background-color: #3ba4d7;
text-align: center;
}

View File

@ -1,81 +0,0 @@
.chat
$color: black
$header_height: 50px
$left_width: 200px
$right_width: 200px
$input_height: 100px
padding: 15px
&.container
height: 100%
padding: 0px
position: relative
box-sizing: border-box
&.header
position: absolute
top: 0px
left: 0px
right: 0px
height: $header_height
background-color: $color
border-bottom: solid 1px gray
box-sizing: border-box
&.left
position: absolute
top: $header_height
bottom: 0px
left: 0px
width: $left_width
//border-right: solid 1px gray
box-sizing: border-box
background-color: black
&.right
position: absolute
top: $header_height
right: 0px
bottom: 0px
width: $right_width
box-sizing: border-box
//border-left: solid 1px gray
&.middle
//background-color: blue
position: absolute
top: 0px
margin-top: $header_height
left: $left_width
right: $right_width
box-sizing: border-box
padding: 0px
height: 100%
overflow-y: scroll
&.bottom
position: absolute
bottom: 0px
right: $right_width
left: $left_width
padding: 5px
&.msg
padding: 0px
$author_width: 100px
&.container
position: relative
border-bottom: solid 1px lightgray
padding: 10px
height: unset
//background-color: lime
&.from
position: absolute
width: $author_width
top: 10px
left: 0px
color: white
text-align: right
&.when
float: right
color: lightgray
margin-bottom: 10px
&.text
padding-left: $author_width
top: 0px
left: $author_width
white-space: pre-wrap
height: initial

View File

@ -1,242 +0,0 @@
body {
background-color: azure;
color: black;
font-family: monospace;
margin: 0em;
/*padding: 1.5em;*/
padding: 2mm;
font-size: 0.9em;
box-sizing: border-box;
}
#overlay {
z-index: 10;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0.5, 0.5, 0.5, 0.8);
}
.paddingbox {
padding: 2mm;
}
.nav {
list-style-type: none;
padding: 0em;
margin: 0em;
}
.nav li {
display: inline;
padding: 0.1em;
margin-right: 1em;
border-width: 0.1em;
border-color: blue;
border-bottom-style: solid;
cursor: pointer;
}
td {
padding: 0.3em;
border-style: solid;
border-width: 0.1em;
border-color: black;
}
hr {
color: black;
}
.menu {
border-style: solid;
border-color: black;
border-width: 0.1em;
cursor: pointer;
padding: 0em;
}
.btn {
border-style: solid;
border-color: black;
border-width: 0.1em;
cursor: pointer;
padding: 0.1em;
}
.btn2,
.box {
border-style: solid;
/*border-color: black;*/
border-color: black;
/*border-width: 1px;*/
border-radius: 0mm;
padding: 2mm;
font-size: 10mm;
cursor: pointer;
margin-bottom: 2mm;
}
.btn2:hover {
background-color: midnightblue;
}
.btnSmall {
border-style: solid;
/*border-color: black;*/
border-color: black;
/*border-width: 1px;*/
border-radius: 0mm;
padding: 1mm;
font-size: 100%;
cursor: pointer;
margin-bottom: 0mm;
}
.hidden {
display: none;
}
.noBorderTable {
width: 100%;
border: none;
border-collapse: collapse;
}
.noBorderTD {
border: none;
border-collapse: collapse;
vertical-align: center;
}
.filelink {
color: inherit;
}
input,
textarea {
color: black;
font-family: monospace;
background-color: azure;
border-color: black;
font-size: 10mm;
border-radius: 0mm;
border-width: 1mm;
padding: 2mm;
margin-bottom: 1mm;
margin-right: 1mm;
/* make the button the whole screen width */
width: 100%;
/* make the text input fit small screens*/
box-sizing: border-box;
}
input:hover {
background-color: midnightblue;
}
textarea#txtNewMsg {
color: black;
font-family: monospace;
background-color: azure;
border-color: black;
font-size: 100%;
border-radius: 0mm;
border-width: 1mm;
padding: 2mm;
margin-bottom: 0mm;
margin-right: 1mm;
height: 110px;
resize: none;
/* make the button the whole screen width */
width: 100%;
/*height: 100%;*/
/* make the text input fit small screens*/
box-sizing: border-box;
}
textarea#certificate {
color: black;
font-family: courrier;
background-color: azure;
border-color: black;
font-size: 100%;
border-radius: 0mm;
border-width: 1mm;
padding: 2mm;
margin-bottom: 0mm;
margin-right: 1mm;
height: 110px;
resize: none;
/* make the button the whole screen width */
width: 100%;
/*height: 100%;*/
/* make the text input fit small screens*/
box-sizing: border-box;
}
input#txtMsgKeyword {
color: black;
font-family: monospace;
background-color: azure;
border-color: black;
font-size: 100%;
border-radius: 0mm;
border-width: 1mm;
padding: 1mm;
margin-bottom: 0mm;
margin-right: 1mm;
/* make the button the whole screen width */
width: 100%;
/* make the text input fit small screens*/
box-sizing: border-box;
}
.checkbox {
width: auto;
}
.flexbox {
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
.flexwidemember {
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: 1; /* OLD - Firefox 19- */
width: 20%; /* For old syntax, otherwise collapses. */
-webkit-flex: 1; /* Chrome */
-ms-flex: 1; /* IE 10 */
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
#logo_splash {
-webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
animation-fill-mode: forwards;
-webkit-animation-name: logo_splash; /* Chrome, Safari, Opera */
-webkit-animation-duration: 3s; /* Chrome, Safari, Opera */
animation-name: logo_splash;
animation-duration: 3s;
text-align: center;
}
/* Chrome, Safari, Opera */
@-webkit-keyframes logo_splash {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Standard syntax */
@keyframes logo_splash {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

View File

@ -1,290 +0,0 @@
body {
background-color: #ccc;
color: #666;
font-family: sans;
margin: 0em;
/*padding: 1.5em;*/
padding: 2mm;
font-size: 1.1em;
box-sizing: border-box;
}
h2 {
text-transform: uppercase;
}
#overlay {
z-index: 10;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
}
.paddingbox {
padding: 2mm;
}
.nav {
list-style-type: none;
padding: 0em;
margin: 0em;
}
.nav li {
display: inline;
padding: 0.1em;
margin-right: 1em;
border-width: 0.1em;
border-color: blue;
border-bottom-style: solid;
cursor: pointer;
}
td {
padding: 0.3em;
border-style: none;
border-width: 0.1em;
border-color: orange;
}
li {
list-style: none;
}
.btn {
cursor: pointer;
padding: 0.1em;
}
input[type='button'] {
border: solid 1px rgba(0, 0, 0, 0);
border-radius: 10px;
font-size: 6mm;
cursor: pointer;
color: #333;
background-color: #f79e3a;
width: 26vw;
display: inline-grid;
margin: 0.2rem;
padding: 0.5rem;
text-align: center;
text-transform: capitalize;
box-shadow: 5px 5px 9px #aaa;
word-break: break-all;
}
.btn2,
.box,
.btnSmall {
border: solid 1px rgba(0, 0, 0, 0);
border-radius: 10px;
font-size: 6mm;
cursor: pointer;
color: #333;
background-color: #f79e3a;
display: inline-grid;
margin: 0.2rem;
padding: 0.5rem;
text-align: center;
text-transform: capitalize;
box-shadow: 5px 5px 9px #aaa;
}
.btn2,
.box {
width: 12rem;
}
.btnSmall {
width: 7rem;
}
.menu {
border: solid 1px rgba(0, 0, 0, 0);
border-radius: 10px;
font-size: 0.8em;
cursor: pointer;
background-color: #f79e3a;
display: inline-grid;
margin: 0.2rem;
padding: 0.5rem;
text-align: center;
text-transform: capitalize;
width: 7rem;
}
span.menu:nth-child(2) {
background-color: rgba(0, 0, 0, 0);
width: 6.3rem;
}
span.menu:nth-child(16) {
background-color: rgba(0, 0, 0, 0);
}
li .menu {
background-color: rgba(0, 0, 0, 0.3);
}
div.btn2:nth-child(9) {
border: rgba(0, 0, 0, 0);
background-color: rgba(0, 0, 0, 0);
text-decoration: underline;
box-shadow: unset;
margin-top: 1em;
text-align: left !important;
font-size: 1em;
}
div.btn2:nth-child(9):hover {
color: #666;
}
.btn2:hover {
background-color: orangered;
color: white;
}
.hidden {
display: none;
}
.noBorderTable {
width: 100%;
border: none;
border-collapse: collapse;
}
.noBorderTD {
border: none;
border-collapse: collapse;
vertical-align: center;
}
.filelink {
color: inherit;
}
input,
textarea {
border-color: orange;
font-size: 10mm;
border-radius: 3mm;
border-width: 1mm;
padding: 2mm;
margin-bottom: 1mm;
margin-right: 1mm;
/* make the button the whole screen width */
width: 100%;
/* make the text input fit small screens*/
box-sizing: border-box;
}
input[type='button']:hover {
background-color: orangered;
}
/*chat*/
textarea#txtNewMsg {
font-size: 100%;
border-radius: 3mm;
border-width: 1mm;
padding: 2mm;
margin-bottom: 0mm;
margin-right: 1mm;
height: 110px;
resize: none;
/* make the button the whole screen width */
width: 100%;
/*height: 100%;*/
/* make the text input fit small screens*/
box-sizing: border-box;
}
input#txtMsgKeyword {
/* color: orange;
font-family: monospace;
background-color: black;*/
border-color: orange;
font-size: 100%;
border-radius: 3mm;
border-width: 1mm;
padding: 1mm;
margin-bottom: 0mm;
margin-right: 1mm;
/* make the button the whole screen width */
width: 100%;
/* make the text input fit small screens*/
box-sizing: border-box;
}
.checkbox {
width: auto;
}
.flexbox {
display: -webkit-box;
/* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box;
/* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox;
/* TWEENER - IE 10 */
display: -webkit-flex;
/* NEW - Chrome */
display: flex;
/* NEW, Spec - Opera 12.1, Firefox 20+ */
}
.flexwidemember {
-webkit-box-flex: 1;
/* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: 1;
/* OLD - Firefox 19- */
width: 20%;
/* For old syntax, otherwise collapses. */
-webkit-flex: 1;
/* Chrome */
-ms-flex: 1;
/* IE 10 */
flex: 1;
/* NEW, Spec - Opera 12.1, Firefox 20+ */
}
#logo_splash {
-webkit-animation-fill-mode: forwards;
/* Chrome, Safari, Opera */
animation-fill-mode: forwards;
-webkit-animation-name: logo_splash;
/* Chrome, Safari, Opera */
-webkit-animation-duration: 3s;
/* Chrome, Safari, Opera */
animation-name: logo_splash;
animation-duration: 3s;
text-align: center;
}
/* Chrome, Safari, Opera */
@-webkit-keyframes logo_splash {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Standard syntax */
@keyframes logo_splash {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

View File

@ -1,17 +1,55 @@
.widget {
margin: 1em;
padding: 1em;
border-radius: 10px;
height: 100%;
padding: 1rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
background-color: white;
border-radius: 6px;
overflow: auto;
& .top-heading {
display: flex;
justify-content: space-between;
}
&__heading {
padding-bottom: 0.25rem;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #999;
}
&__body {
height: 100%;
display: flex;
flex-direction: column;
overflow: auto;
&-heading {
display: flex;
justify-content: space-between;
align-items: center;
& .action {
display: flex;
gap: 0.5rem;
}
}
&-content {
height: 100%;
overflow: auto;
}
&-box {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
}
& > p {
font-size: 0.9em;
color: #666;
}
& .tooltip {
float: right;
}
&-half {
max-width: 50%;
}
}
.widget > p {
font-size: 0.9em;
color: #666;
}
.widget .tooltip {
float: right;
}
.widget-half {
max-width: 50%;
}

View File

@ -1,10 +1,3 @@
.board-node-panel {
position: relative;
bottom: 200px;
margin-left: 200px;
animation: fadein 0.5s;
}
/* subject */
table.boards th:nth-child(1) {
width: 50%;
@ -24,77 +17,15 @@ table.boards tr:hover {
cursor: pointer;
}
table.boards tr.hidden{
table.boards tr.hidden {
display: none;
}
#searchboard {
position:relative;
margin-left: 250px;
}
img.boardpic {
float: left;
height: 150px;
width:150px;
padding: 25px;
}
#boarddetails {
position: relative;
margin-left: 150px;
padding: 10px;
}
.p{
margin:0;
}
#toggleunsub {
position: relative;
background: gray;
}
#grid{
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
gap: 100px;
}
.card {
width: 150px;
height: 200px;
border: 2px solid gray;
cursor: pointer;
text-align: center;
}
.card-img {
width: 120px;
height: 120px;
}
.card-title {
position: relative;
bottom: 0px;
overflow: auto;
}
/* subject */
table.comments th {
height: 40px;
}
table.comments th:nth-child(1) {
width: 40%;
}
table.comments td {
word-wrap: break-word;
}
table.comments td:nth-child(1){
border: 3px solid lightskyblue;
border-radius: 25px;
}
table.comments tr {
height: 40px;
}
#options {
width: 100px;
text-align: center;
@ -116,4 +47,4 @@ table.comments tr {
font-size: medium;
margin-left: 10px;
height: 40px;
}
}

View File

@ -1,110 +1,87 @@
.channel-node-panel {
position: relative;
bottom: 200px;
margin-left: 200px;
animation: fadein 0.5s;
@use '../abstracts/colors' as *;
.file-section {
margin-top: 2rem;
display: flex;
flex-direction: column;
}
/* subject */
table.channels th:nth-child(1) {
width: 50%;
text-align: start;
}
/* subject */
table.channels td:nth-child(1) {
text-align: start;
/* Truncate text with '...' */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.comments-section {
margin-top: 2rem;
display: flex;
justify-content: space-between;
&__menu {
display: flex;
gap: 1rem;
&-id {
display: flex;
gap: 0.25rem;
align-items: center;
}
}
}
table.channels tr:hover {
background-color: #eef3f6;
cursor: pointer;
}
table.channels tr.hidden {
display: none;
}
#searchchannel {
position: relative;
margin-left: 250px;
/* top: px; */
}
img.channelpic {
float: left;
height: 150px;
width: 150px;
padding: 25px;
}
#channeldetails {
position: relative;
margin-left: 150px;
padding: 10px;
}
.p {
margin: 0;
}
#toggleunsub {
position: relative;
background: gray;
}
#grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
gap: 100px;
}
.card {
width: 150px;
height: 200px;
border: 2px solid gray;
cursor: pointer;
text-align: center;
}
.card-img {
width: 120px;
height: 120px;
}
.card-title {
position: relative;
bottom: 0px;
overflow: auto;
/* subject */
table.channels {
& th:nth-child(1) {
width: 50%;
text-align: start;
}
/* subject */
& td:nth-child(1) {
text-align: start;
/* Truncate text with '...' */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
& tr:hover {
background-color: $light-color;
cursor: pointer;
}
& tr.hidden {
display: none;
}
}
/* subject */
table.comments th {
height: 40px;
}
table.comments th:nth-child(1) {
width: 2%;
}
table.comments th:nth-child(2) {
width: 40%;
}
table.comments td {
word-wrap: break-word;
}
table.comments td:nth-child(2) {
text-align: start;
border: 3px solid lightskyblue;
border-radius: 25px;
}
table.comments tr {
height: 40px;
}
table.files th:nth-child(1) {
width: 40%;
}
table.files th:nth-child(3) {
width: 50%;
}
table.files td {
word-wrap: break-word;
table {
padding: 0.5rem;
&.comments {
border: 1px solid #eee;
& th {
height: 40px;
&:nth-child(1) {
width: 2%;
}
&:nth-child(2) {
width: 40%;
}
}
& td {
word-wrap: break-word;
&:nth-child(2) {
text-align: start;
}
}
}
&.files {
& th:first-child {
text-align: start;
width: 60%;
}
& tr td:first-child {
text-align: start;
}
& td {
word-wrap: break-word;
}
}
}
/* #options{
width: 100px;

View File

@ -81,7 +81,7 @@
.lobbies {
position: absolute;
width: 185px;
left: 138px;
left: 165px;
bottom: 15px;
top: 130px;
overflow: auto;
@ -92,7 +92,7 @@
position: absolute;
background-color: white;
top: 130px;
left: 328px;
left: 360px;
right: 215px;
overflow: auto;
}
@ -121,7 +121,7 @@
height: 85px;
bottom: 15px;
right: 215px;
left: 323px;
left: 360px;
}
textarea.chatMsg {

View File

@ -1,29 +1,15 @@
@use '../abstracts/variables' as *;
.config-node-panel {
position: relative;
bottom: 320px;
margin-left: 200px;
animation: fadein 0.5s;
}
@use '../abstracts/colors' as *;
.mail {
.permission-flag {
margin-bottom: 1rem;
display: flex;
gap: 1rem;
}
&-tags {
padding: 8px;
padding: 0.5rem;
border: 1px solid transparentize($dark-color, 0.8);
border-radius: 6px;
&__heading {
display: flex;
justify-content: space-between;
align-items: center;
& button {
height: max-content;
}
}
&__container {
display: flex;
flex-direction: column;
@ -38,12 +24,12 @@
border: none;
}
&__color {
width: 20px;
height: 20px;
width: 1.25rem;
height: 1.25rem;
aspect-ratio: 1;
}
&__name {
font-size: 1.25rem;
font-size: 1.125rem;
}
&__modify {
margin-left: auto;
@ -54,6 +40,10 @@
&:hover {
background-color: $light-color;
}
& button,
& button.red {
padding: 0.25rem 0.6rem;
}
}
}
}
@ -70,7 +60,7 @@
margin: 0;
padding-left: 1rem;
height: 100px;
overflow: hidden scroll;
overflow: hidden auto;
&::-webkit-scrollbar {
display: none;
}
@ -102,3 +92,9 @@
}
}
}
.config-files {
display: flex;
flex-direction: column;
gap: 1rem;
}

View File

@ -1,56 +1,47 @@
@use '../abstracts/variables' as *;
@use '../abstracts/colors' as *;
.file-view {
width: 90%;
border-radius: 10px;
width: 100%;
padding: 1rem;
margin-top: 1.5rem;
border-radius: 8px;
border: 1px solid #ccc;
margin-top: 2em;
padding: 1em;
animation: fadein 0.5s;
}
.file-view > p {
margin: 0.5em;
font-size: 1.1em;
}
.file-view > span {
margin: 0 1em;
font-size: 0.9em;
}
.file-view > .progressbar {
width: 70%;
margin-bottom: 5px;
}
.file-view button {
float: right;
margin-left: 15px;
}
.file-view select {
float: right;
margin-left: 15px;
}
.file-view label {
float: right;
margin-left: 15px;
}
span > i {
margin-right: 5px;
}
.filestat {
min-width: 7em;
display: inline-block;
}
.searchbar {
margin: 5px;
width: 40%;
box-shadow: 0 0 3px #aaa;
}
.file-node-panel {
position: relative;
bottom: 200px;
margin-left: 200px;
animation: fadein 0.5s;
&__heading {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
&-chunk {
display: flex;
gap: 1rem;
}
}
&__body {
display: flex;
flex-direction: column;
gap: 0.5rem;
&-details {
display: flex;
align-items: center;
&-stat {
width: 100%;
display: grid;
grid-template-columns: repeat(5, 1fr);
& span > i {
margin-right: 0.5rem;
}
}
&-action {
display: flex;
height: 100%;
gap: 1rem;
& button,
& button.red {
padding: 0.25rem 0.75rem;
}
}
}
}
}
table.myfiles td {
@ -89,10 +80,8 @@ table.friendsfiles td:nth-child(2) {
gap: 8px;
border: 1px solid transparentize($dark-color, 0.8);
border-radius: 6px;
h4 {
font-size: 1.25rem;
}
height: 100%;
overflow: auto;
&__keywords {
flex-basis: 15%;
@ -116,6 +105,8 @@ table.friendsfiles td:nth-child(2) {
&__results {
flex-basis: 85%;
height: 100%;
overflow: auto;
& .results-container {
& .results-header {
@ -144,6 +135,8 @@ table.friendsfiles td:nth-child(2) {
}
}
& .results {
height: 100%;
overflow: auto;
& tr {
display: flex;
& .results {
@ -171,9 +164,17 @@ table.friendsfiles td:nth-child(2) {
}
}
}
& button {
font-size: 1rem;
}
}
}
}
.search-form {
display: flex;
width: 40%;
input {
width: 100%;
}
button {
margin-left: 0.5rem;
}
}

View File

@ -70,10 +70,3 @@ table.threadreply tr:hover {
background-color: #eef3f6;
cursor: pointer;
}
#idtags{
width: 160px;
text-align: center;
font-size: medium;
margin-left: 10px;
height: 40px;
}

View File

@ -1,52 +1,124 @@
.certificate {
margin: auto;
@use '../abstracts/colors' as *;
.homepage {
margin: 2rem auto 0;
display: flex;
align-items: flex-start;
flex-direction: column;
align-items: center;
margin-top: 20px;
}
.textArea {
box-sizing: none;
background: transparent;
font-size: 1.1rem;
border-radius: 5px;
border: none;
resize: none;
}
.logo {
display: flex;
max-width: 500px;
justify-content: center;
align-items: center;
}
.retroshareText > h3 {
margin-right: 3px;
}
.webhelp {
background: whitesmoke;
font-size: 0.8rem;
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
color: black;
border-radius: 5px;
border: 1px solid black;
padding: 10px 14px;
cursor: pointer;
}
.webhelp > i {
font-size: 1.2rem;
}
.webhelp > p {
font-weight: 600;
}
.retroshareID {
display: flex;
justify-self: start;
align-items: center;
font-size: 1.2rem;
font-family: monospace;
gap: 4rem;
.logo {
display: flex;
justify-content: center;
align-items: center;
& img {
width: 90px;
}
.retroshareText {
display: flex;
flex-direction: column;
align-items: center;
& .retrotext {
font-size: 36px;
line-height: 1.125;
font-weight: 500;
& > span {
color: $primary-retro-color;
}
}
& > b {
font-size: 14px;
line-height: 1;
}
}
}
.certificate {
display: flex;
flex-direction: column;
gap: 4rem;
&__heading {
text-align: center;
& > h1 {
margin-bottom: 1rem;
}
}
&__content {
display: flex;
flex-direction: column;
gap: 2rem;
padding: 2rem;
text-align: center;
border: 1.5px solid transparentize($primary-retro-color, 0.8);
border-radius: 6px;
box-shadow: 0px 0px 8px 2px transparentize($dark-color, 0.95);
.rsId > p {
margin-bottom: 0.5rem;
color: $primary-retro-color;
}
.retroshareID {
padding: 0.5rem;
display: flex;
justify-self: start;
align-items: center;
font-size: 1.2rem;
border-radius: 4px;
background: transparentize($dark-color, 0.95);
& .textArea {
padding: 0;
font-size: 1rem;
font-family: monospace;
box-sizing: none;
background: transparent;
font-size: 1.1rem;
border-radius: 5px;
border: none;
resize: none;
}
& i {
color: $primary-retro-color;
}
& > i {
margin: 0 0.5rem;
cursor: pointer;
}
}
.webhelp {
&-container {
display: grid;
place-items: center;
}
background: whitesmoke;
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
border-radius: 5px;
border: 1px solid transparentize($dark-color, 0.5);
padding: 0.5rem;
width: fit-content;
cursor: pointer;
&:hover {
background: $light-color;
border: 1px solid $dark-color;
}
& > i {
font-size: 1.2rem;
color: green;
}
}
.add-friend > h6,
.webhelp-container > h6 {
font-weight: normal;
margin-bottom: 0.5rem;
}
}
}
}

View File

@ -1,4 +1,89 @@
@use '../abstracts' as *;
@use '../abstracts/colors' as *;
.side-bar {
display: flex;
flex-direction: column;
background: white;
.mail-compose-btn {
width: 96%;
margin: 0.25rem;
padding: 0.75rem 0;
}
}
.msg-view {
height: 100%;
display: flex;
flex-direction: column;
gap: 1rem;
overflow: auto;
&-nav {
display: flex;
justify-content: space-between;
align-items: center;
&__action {
display: flex;
gap: 0.5rem;
}
}
&__header {
display: flex;
flex-direction: column;
gap: 1rem;
& > h3 {
line-height: 1;
}
& .msg-details {
display: flex;
gap: 1rem;
&__avatar {
height: max-content;
}
&__info {
display: flex;
flex-direction: column;
&-item {
display: flex;
gap: 0.5rem;
}
}
}
}
&__body {
height: 100%;
overflow: auto;
iframe {
width: 100%;
height: 98%;
border: none;
}
}
&__attachment {
height: 50%;
overflow: auto;
display: flex;
flex-direction: column;
&-items {
height: 100%;
overflow: auto;
}
}
}
iframe.msg {
border: 0;
}
.mail-tag {
width: 8rem;
padding: 0.5rem;
}
.msgHeader {
display: flex;
}
.msgHeaderDetails {
display: flex;
flex-direction: column;
}
table.mails {
& th {
@ -74,73 +159,22 @@ input.star-check {
}
/* mail_util.js styles */
.truncate {
display: flex;
width: 65vw;
height: 22px;
flex-wrap: wrap;
gap: 4px;
#truncate {
height: 1.75rem;
overflow: hidden;
}
#show-more,
#show-less {
font-size: 0.8em;
width: 100px;
height: max-content;
}
iframe.msg {
border: 0;
width: 100%;
height: 450px;
}
#composebtn {
text-align: center;
width: 200px;
height: 50px;
/* float: left; */
}
#searchmail {
float: right;
position: relative;
margin-right: 20px;
}
#tags {
width: 200px;
text-align: center;
font-size: medium;
margin-left: 20px;
height: 40px;
}
#composepopup {
height: 80%;
width: 70%;
bottom: 50%;
right: 58%;
}
.mail-node-panel {
position: relative;
bottom: 755px;
margin-left: 200px;
animation: fadein 0.5s;
}
.msgHeader {
display: flex;
}
.msgHeaderDetails {
display: flex;
flex-direction: column;
font-size: 0.75rem;
padding: 0 0.25rem;
background: #999;
color: $dark-color;
box-shadow: none;
border-radius: 2px;
}
// Normal mail attachment view
table.attachment-container {
height: auto;
overflow-y: scroll;
display: flex;
flex-direction: column;
gap: 2px;
padding: 0;
& > tr {
@ -153,17 +187,20 @@ table.attachment-container {
justify-content: space-between;
th {
font-size: 1.5rem;
text-align: start;
&:nth-child(1) {
flex-basis: 45%;
}
&:nth-child(2),
&:nth-child(3),
&:nth-child(4) {
&:nth-child(2) {
flex-basis: 15%;
}
&:nth-child(3) {
flex-basis: 10%;
}
&:nth-child(4) {
flex-basis: 20%;
}
&:nth-child(5) {
text-align: center;
flex-basis: 10%;
@ -188,11 +225,15 @@ table.attachment-container {
}
}
&__from,
&__size,
&__date {
&__from {
flex-basis: 15%;
}
&__size {
flex-basis: 10%;
}
&__date {
flex-basis: 20%;
}
& td:nth-child(5) {
display: flex;
justify-content: center;
@ -200,28 +241,21 @@ table.attachment-container {
flex-basis: 10%;
& button {
font-size: inherit;
font-size: 0.875rem;
}
}
}
}
// Attachment Section attachment view
.msg-attachment-container {
.view-toggle {
height: max-content;
border: 1px solid $primary-color;
border-radius: 4px;
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
& .view-toggle {
height: max-content;
border: 1px solid $primary-color;
& * {
padding: 4px 12px;
border-radius: 4px;
display: flex;
& * {
padding: 4px 12px;
border-radius: 4px;
}
}
}

View File

@ -1,48 +1,45 @@
.friend {
color: #444;
font-size: 1.2em;
margin: 1em;
padding: 20px;
margin: 1rem 0.5rem;
padding: 1.5rem;
border: 1px solid #aaa;
border-radius: 20px;
}
.friend i {
float: left;
padding: 0 10px;
cursor: pointer;
}
.friend h4 {
margin-bottom: 5px;
}
.friend p {
margin: 0;
}
.friend button {
font-size: 0.9em;
}
.friend.hidden {
display: none;
}
.friend .brief-info.online {
color: green;
}
& i {
float: left;
padding: 0 10px;
cursor: pointer;
}
& h4 {
margin-bottom: 5px;
}
& button {
font-size: 0.9em;
}
&.hidden {
display: none;
}
& .brief-info.online {
color: green;
}
.friend .location {
margin: 5px;
border-top: 1px solid #bbb;
display: grid;
grid-template-columns: auto auto;
justify-content: start;
}
.friend .brief-info {
display: flex;
align-items: center;
justify-self: start;
}
& .location {
margin: 5px;
border-top: 1px solid #bbb;
display: grid;
grid-template-columns: auto auto;
justify-content: start;
}
& .brief-info {
display: flex;
align-items: center;
justify-self: start;
}
.friend .fa-times-circle {
color: #555;
}
.friend .fa-check-circle {
color: green;
& .fa-times-circle {
color: #555;
}
& .fa-check-circle {
color: green;
}
}

View File

@ -5,16 +5,19 @@
padding: 10px;
border: 1px solid #aaa;
border-radius: 20px;
}
.identity > h4 {
margin: 5px;
font-size: 1.3em;
}
.identity p {
margin: 0;
}
.identity button {
font-size: 0.9em;
& > h4 {
margin: 5px;
font-size: 1.3em;
}
& button {
font-size: 0.9em;
}
& .details {
display: grid;
grid-template-columns: 140px auto;
grid-row-gap: 5px;
justify-content: left;
}
}
.defaultAvatar {
@ -25,35 +28,29 @@
border-radius: 50%;
display: grid;
place-items: center;
}
.defaultAvatar p {
font-weight: 900;
color: #666F7F;
transform: translateY(1px);
& p {
font-weight: 900;
color: #666f7f;
transform: translateY(1px);
}
}
img.avatar {
display: block;
width: 50px;
height: max-content;
aspect-ratio: 1;
margin-right: 0.3em;
border-radius: 50%;
}
.identity .details {
display: grid;
grid-template-columns: 140px auto;
grid-row-gap: 5px;
justify-content: left;
}
.counter {
margin-left: 0.5em;
}
.counter:before {
content: '(';
}
.counter:after {
content: ')';
&:before {
content: '(';
}
&:after {
content: ')';
}
}
.chatInit {

File diff suppressed because one or more lines are too long