Skip to content

Commit

Permalink
Private groups, Mobile app - fixes (still WIP...)
Browse files Browse the repository at this point in the history
  • Loading branch information
1aerostorm committed Dec 11, 2024
1 parent 5843c86 commit aef0353
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 17 deletions.
20 changes: 18 additions & 2 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import AppSettings, { openAppSettings } from 'app/components/pages/app/AppSettin
import Themifier from 'app/Themifier'
import Translator from 'app/Translator'
import initConfig from 'app/utils/initConfig'
import RenderError from 'app/utils/RenderError'
import { getShortcutIntent, onShortcutIntent } from 'app/utils/app/ShortcutUtils'

import 'app/App.scss'
Expand Down Expand Up @@ -68,6 +69,20 @@ class App extends React.Component {
})
}

componentDidCatch(err, info) {
console.error('Render error:', err, info)
const errStr = (err && err.toString()) ? err.toString() : JSON.stringify(err)
const infoStr = (info && info.componentStack) || JSON.stringify(info)
this.setState({
fatalErr: {
errStr,
infoStr
}
})
//alert(';( Ошибка рендеринга\n\n' + errStr + '\n' + infoStr)
//throw err
}

showAppReminder = () => {
if (process.env.MOBILE_APP || process.env.DESKTOP_APP) {
return
Expand All @@ -87,10 +102,11 @@ class App extends React.Component {
</div>
}
const reminder = this.showAppReminder() ? <AppReminder /> : null
const { fatalErr } = this.state
return (
<Provider store={store}>
<Translator>
<ConnectedRouter history={history}>
{fatalErr ? <RenderError error={fatalErr} /> : <ConnectedRouter history={history}>
<Switch>
<Route path='/__app_settings'>
<Themifier>
Expand All @@ -110,7 +126,7 @@ class App extends React.Component {
</Themifier>}
</Route>
</Switch>
</ConnectedRouter>
</ConnectedRouter>}
</Translator>
</Provider>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
}

.conversation-info {
width: 100%;
max-width: 98%;
}

.conversation-snippet {
Expand Down
60 changes: 51 additions & 9 deletions src/components/modules/groups/MyGroups.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ class MyGroups extends React.Component {

refetch = () => {
const { currentUser } = this.props
this.props.fetchMyGroups(currentUser)
this.setState({
currentTab: null,
}, () => {
this.props.fetchMyGroups(currentUser)
})
}

componentDidMount = async () => {
Expand Down Expand Up @@ -124,7 +128,7 @@ class MyGroups extends React.Component {
}

_renderGroup = (group) => {
const { name, json_metadata, pendings } = group
const { name, json_metadata, pendings, members, moders, } = group

const meta = getGroupMeta(json_metadata)

Expand Down Expand Up @@ -156,6 +160,9 @@ class MyGroups extends React.Component {
}, value: tt('msgs_group_dropdown.retire') })
}


const noMembers = !pendings && !members && !moders

return <tr key={name}>
<Link to={'/' + name} onClick={this.onGoGroup}>
{this._renderGroupLogo(group, meta)}
Expand Down Expand Up @@ -183,8 +190,10 @@ class MyGroups extends React.Component {
{(isSmall ? '' : tt('group_members_jsx.check_pending')) + ' (' + pendings + ')'}
</span>
</button> : null}
<button className={cn('button force-white', {
'icon-only': (isSmall || pendings || amPending)
<button className={cn('button', {
'force-white': !noMembers,
'icon-only': (isSmall || pendings || amPending),
hollow: noMembers,
})} onClick={e => {
this.showGroupMembers(e, group)
}} title={(isSmall || pendings || amPending) ? tt('my_groups_jsx.members') : null}>
Expand All @@ -205,6 +214,28 @@ class MyGroups extends React.Component {
</tr>
}

_renderGroupTypeSwitch = () => {
const { stat, } = this.props
let { currentTab } = this.state
currentTab = currentTab || stat.current
let tabs = []
for (const key of ['pending', 'member', 'moder', 'own']) {
if (!stat[key]) continue
tabs.push(<div key={key} className={cn('label', { checked: (key === currentTab) })}
onClick={e => {
this.setState({
currentTab: key
})
}} >
{tt('my_groups_jsx.tab_' + key) + ' (' + stat[key] + ')'}
</div>)
}
if (tabs.length < 1) return null
return <div style={{ marginBottom: '1rem' }} title={tt('my_groups_jsx.tabs_title')}>
{tabs}
</div>
}

render() {
let groups, hasGroups

Expand All @@ -231,15 +262,24 @@ class MyGroups extends React.Component {
</div>
} else {
hasGroups = true

const { stat, } = this.props
let { currentTab } = this.state
currentTab = currentTab || stat.current

groups = []
for (const g of my_groups) {
if (currentTab && g.my_role !== currentTab) continue
groups.push(this._renderGroup(g))
}
groups = <table>
<tbody>
{groups}
</tbody>
</table>
groups = <React.Fragment>
{this._renderGroupTypeSwitch()}
<table>
<tbody>
{groups}
</tbody>
</table>
</React.Fragment>
}
}

Expand Down Expand Up @@ -276,11 +316,13 @@ export default connect(
const currentUser = state.user.getIn(['current'])
const username = currentUser && currentUser.get('username')
const my_groups = state.global.get('my_groups')
const my_groups_stat = state.global.get('my_groups_stat')

return { ...ownProps,
currentUser,
username,
my_groups,
stat: my_groups_stat ? my_groups_stat.toJS() : {},
}
},
dispatch => ({
Expand Down
19 changes: 19 additions & 0 deletions src/components/modules/groups/MyGroups.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,23 @@
.button.force-white {
color: #fefefe !important;
}
.label {
padding: 0.5rem;
transition: all .1s ease-in;
user-select: none;

margin-right: 0.5rem;

&:not(.disabled) {
cursor: pointer;
}
&:not(.checked) {
background: #f4f4f8;
color: #333333;
}
&:hover:not(.disabled) {
background: #0078C4;
color: #fefefe;
}
}
}
3 changes: 3 additions & 0 deletions src/components/modules/groups/TopGroups.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
vertical-align: middle;
img {
border-radius: 50%;
width: 50px;
height: 50px;
object-fit: cover;
}
}
.group-stats {
Expand Down
11 changes: 10 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,13 @@
"login_hint_GROUP": "(delete \"%(GROUP)s\" group)",
"members": "Members",
"cancel_pending": "Cancel request",
"are_you_sure_cancel": "Do you sure you don't want to join"
"are_you_sure_cancel": "Do you sure you don't want to join",
"tab_pending": "Pending",
"tab_member": "Member",
"tab_moder": "Moder",
"tab_own": "Owner",
"tabs_title": "Your status in groups",
"total_MEMBERS": "Total: %(MEMBERS)s member(-s)."
},
"top_groups_jsx": {
"title": "Popular Groups",
Expand Down Expand Up @@ -266,6 +272,9 @@
"flags": "Флаги"
}
},
"fatal_error_jsx": {
"render_error": ";( Render Error"
},
"stub_jsx": {
"read_only": "Only members can post messages in this group.",
"private_group": "This group is private. To read and write messages, you should be a member.",
Expand Down
11 changes: 10 additions & 1 deletion src/locales/ru-RU.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,13 @@
"login_hint_GROUP": "(удаления группы \"%(GROUP)s\")",
"members": "Участники",
"cancel_pending": "Отменить заявку",
"are_you_sure_cancel": "Вы уверены, что хотите отказаться от вступления в группу"
"are_you_sure_cancel": "Вы уверены, что хотите отказаться от вступления в группу",
"tab_pending": "Заявки",
"tab_member": "Участник",
"tab_moder": "Модератор",
"tab_own": "Владелец",
"tabs_title": "Ваш статус в группах",
"total_MEMBERS": "Всего %(MEMBERS)s участник(-ов)."
},
"top_groups_jsx": {
"title": "Топ популярных групп",
Expand Down Expand Up @@ -282,6 +288,9 @@
"flags": "Флаги"
}
},
"fatal_error_jsx": {
"render_error": ";( Ошибка рендеринга"
},
"stub_jsx": {
"read_only": "Писать сообщения в этой группе могут лишь ее члены.",
"private_group": "Это закрытая группа. Чтобы видеть сообщения и общаться в ней, надо стать ее членом.",
Expand Down
36 changes: 35 additions & 1 deletion src/redux/FetchDataSaga.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import golos, { api, auth } from 'golos-lib-js'
import tt from 'counterpart'

import g from 'app/redux/GlobalReducer'
import { getRoleInGroup } from 'app/utils/groups'
import { getSpaceInCache, saveToCache } from 'app/utils/Normalizators'

export function* fetchDataWatches () {
Expand Down Expand Up @@ -226,6 +227,12 @@ export function* watchFetchMyGroups() {

export function* fetchMyGroups({ payload: { account } }) {
try {
const stat = {
pending: 0,
member: 0,
moder: 0,
own: 0,
}
const groupsOwn = (yield call([api, api.getGroupsAsync], {
member: account,
member_types: [],
Expand All @@ -235,6 +242,7 @@ export function* fetchMyGroups({ payload: { account } }) {
accounts: [account]
}
})).groups

let groups = (yield call([api, api.getGroupsAsync], {
member: account,
member_types: ['pending', 'member', 'moder'],
Expand All @@ -244,12 +252,38 @@ export function* fetchMyGroups({ payload: { account } }) {
accounts: [account]
}
})).groups

groups = [...groupsOwn, ...groups]
for (const group of groups) {
const { amPending, amMember, amModer, amOwner } = getRoleInGroup(group, account)
if (amOwner) {
group.my_role = 'own'
stat.own++
} else if (amPending) {
group.my_role = 'pending'
stat.pending++
} else if (amMember) {
group.my_role = 'member'
stat.member++
} else if (amModer) {
group.my_role = 'moder'
stat.moder++
}
}
groups.sort((a, b) => {
return b.pendings - a.pendings
})

yield put(g.actions.receiveMyGroups({ groups }))
let current = 'member'
if (stat.pending) {
current = 'pending'
} else {
if (stat.moder > stat[current]) current = 'moder'
if (stat.own > stat[current]) current = 'own'
}
stat.current = current

yield put(g.actions.receiveMyGroups({ groups, stat }))
} catch (err) {
console.error('fetchMyGroups', err)
}
Expand Down
7 changes: 5 additions & 2 deletions src/redux/GlobalReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export default createModule({
})
let new_state = state.set('messages', List());
new_state = new_state.set('contacts', List());
new_state = new_state.delete('the_group');
new_state = new_state.mergeDeep(payload)
return new_state
},
Expand Down Expand Up @@ -366,8 +367,10 @@ export default createModule({
},
{
action: 'RECEIVE_MY_GROUPS',
reducer: (state, { payload: { groups } }) => {
return state.set('my_groups', fromJS(groups))
reducer: (state, { payload: { groups, stat } }) => {
let new_state = state.set('my_groups', fromJS(groups))
new_state = new_state.set('my_groups_stat', fromJS(stat))
return new_state
},
},
{
Expand Down
28 changes: 28 additions & 0 deletions src/utils/RenderError.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react'

import tt from 'counterpart'

class RenderError extends React.Component {
refreshIt = () => {
if (window.location.pathname === '/') {
window.location.reload()
return
}
window.location.href = '/'
}

render() {
const { error } = this.props
const refreshBtn = <button className='button' onClick={this.refreshIt}>{tt('g.refresh')}</button>
const { errStr, infoStr } = error
return <div style={{padding: '1rem'}}>
<h4>{tt('fatal_error_jsx.render_error')}</h4><br/>
{refreshBtn}<br/>
<b>{errStr}</b><br/>
<pre>{infoStr}</pre><br/>
{refreshBtn}
</div>
}
}

export default RenderError

0 comments on commit aef0353

Please sign in to comment.