Skip to content
GitLab
Menu
Why GitLab
Pricing
Contact Sales
Explore
Why GitLab
Pricing
Contact Sales
Explore
Sign in
Get free trial
Commits on Source (5)
(feat) add open/close logic to UserModel
· b854aa6d
Martin Santangelo
authored
Oct 14, 2019
b854aa6d
(fix) invariant violation Text strings must be rendered within a Text component
· b43773c8
Martin Santangelo
authored
Oct 14, 2019
b43773c8
(feat) implement open/closed channel
· 69d92731
Martin Santangelo
authored
Oct 14, 2019
69d92731
(feat) do not log network fail, aborts, etc
· 1892c2ed
Martin Santangelo
authored
Oct 14, 2019
1892c2ed
(chore) remove unused import
· ec1cafd9
Martin Santangelo
authored
Oct 14, 2019
ec1cafd9
Hide whitespace changes
Inline
Side-by-side
AppStores.js
View file @
ec1cafd9
...
...
@@ -27,11 +27,13 @@ import groupsBar from './src/groups/GroupsBarStore';
import
sessionService
from
'
./src/common/services/session.service
'
;
import
logService
from
'
./src/common/services/log.service
'
;
import
SubscriptionRequestStore
from
'
./src/channel/subscription/SubscriptionRequestStore
'
;
/**
* App stores
*/
const
stores
=
{
subscriptionRequest
:
new
SubscriptionRequestStore
(),
newsfeed
:
new
newsfeed
(),
notifications
:
new
notifications
(),
notificationsSettings
:
new
notificationsSettings
(),
...
...
locales/en.json
View file @
ec1cafd9
...
...
@@ -211,6 +211,7 @@
"video"
:
"Video"
},
"channel"
:{
"isClosed"
:
"This is a closed channel"
,
"channel"
:
"channel"
,
"errorSaving"
:
"Error saving channel"
,
"saveChanges"
:
"Save your changes"
,
...
...
@@ -220,6 +221,7 @@
"mature"
:
"This channel contains mature content"
,
"confirmUnsubscribe"
:
"Are you sure you want to unsubscribe from this channel?"
,
"subscribe"
:
"Subscribe"
,
"requestSubscription"
:
"Request Subscription"
,
"subscribed"
:
"Subscribed"
,
"subscribeMessage"
:
"Subscribe to this channel"
,
"unsubscribeMessage"
:
"Unsubscribe to this channel"
,
...
...
@@ -234,7 +236,9 @@
"blocked"
:
"You have blocked @{{username}}"
,
"tapUnblock"
:
"Tap to unblock"
,
"notFound"
:
"Channel not found"
,
"viewScheduled"
:
"Scheduled"
"viewScheduled"
:
"Scheduled"
,
"requestAccepted"
:
"Accepted"
,
"requestRejected"
:
"Rejected"
},
"discovery"
:{
"search"
:
"Search..."
,
...
...
@@ -774,5 +778,6 @@
"cantReachServer"
:
"Can't reach the server"
,
"showingStored"
:
"Showing stored data"
,
"actions"
:
"Actions"
,
"requests"
:
"Requests"
,
"notAllowed"
:
"You are not allowed"
}
src/channel/ChannelActions.js
View file @
ec1cafd9
...
...
@@ -49,7 +49,7 @@ class ChannelActions extends Component {
getOptions
()
{
let
options
=
[
i18n
.
t
(
'
cancel
'
)
];
if
(
this
.
props
.
store
.
channel
.
s
ubscribed
){
if
(
this
.
props
.
store
.
channel
.
isS
ubscribed
()
){
options
.
push
(
i18n
.
t
(
'
channel.unsubscribe
'
)
);
}
...
...
@@ -73,10 +73,10 @@ class ChannelActions extends Component {
this
.
props
.
store
.
channel
.
toggleSubscription
();
break
;
case
i18n
.
t
(
'
channel.block
'
):
this
.
props
.
store
.
toggleBlock
();
this
.
props
.
store
.
channel
.
toggleBlock
();
break
;
case
i18n
.
t
(
'
channel.unblock
'
):
this
.
props
.
store
.
toggleBlock
();
this
.
props
.
store
.
channel
.
toggleBlock
();
break
;
case
i18n
.
t
(
'
channel.report
'
):
this
.
props
.
navigation
.
push
(
'
Report
'
,
{
entity
:
this
.
props
.
store
.
channel
});
...
...
@@ -120,6 +120,8 @@ class ChannelActions extends Component {
return
featuresService
.
has
(
'
post-scheduler
'
)
&&
!
this
.
state
.
edit
;
}
setSheetRef
=
o
=>
this
.
ActionSheet
=
o
;
/**
* Render Header
*/
...
...
@@ -129,8 +131,8 @@ class ChannelActions extends Component {
const
isOwner
=
channel
.
isOwner
();
const
showWire
=
!
channel
.
blocked
&&
!
isOwner
&&
featuresService
.
has
(
'
crypto
'
)
&&
channel
.
can
(
FLAG_WIRE
);
const
showScheduled
=
featuresService
.
has
(
'
post-scheduler
'
)
&&
!
this
.
state
.
edit
&&
isOwner
;
const
showSubscribe
=
!
isOwner
&&
!
channel
.
s
ubscribed
&&
channel
.
can
(
FLAG_SUBSCRIBE
);
const
showMessage
=
!
isOwner
&&
channel
.
s
ubscribed
&&
channel
.
can
(
FLAG_MESSAGE
);
const
showSubscribe
=
!
isOwner
&&
!
channel
.
isS
ubscribed
()
&&
channel
.
can
(
FLAG_SUBSCRIBE
);
const
showMessage
=
!
isOwner
&&
channel
.
isS
ubscribed
()
&&
channel
.
can
(
FLAG_MESSAGE
);
const
showEdit
=
isOwner
&&
channel
.
can
(
FLAG_EDIT_CHANNEL
);
if
(
this
.
props
.
store
.
isUploading
)
{
...
...
@@ -198,7 +200,7 @@ class ChannelActions extends Component {
/
>
}
<
ActionSheet
ref
=
{
o
=>
this
.
Action
Sheet
=
o
}
ref
=
{
this
.
set
Sheet
Ref
}
title
=
{
i18n
.
t
(
'
actions
'
)}
options
=
{
this
.
getOptions
()}
onPress
=
{
this
.
handleSelection
}
...
...
src/channel/ChannelFeedStore.js
View file @
ec1cafd9
import
{
observable
,
action
,
computed
,
extendObservable
}
from
'
mobx
'
import
{
getFeedChannel
,
toggleComments
,
toggleExplicit
,
setViewed
}
from
'
../newsfeed/NewsfeedService
'
;
import
api
from
'
../common/services/api.service
'
;
import
channelService
from
'
./ChannelService
'
;
import
OffsetFeedListStore
from
'
../common/stores/OffsetFeedListStore
'
;
import
ActivityModel
from
'
../newsfeed/ActivityModel
'
;
import
BlogModel
from
'
../blogs/BlogModel
'
;
import
logService
from
'
../common/services/log.service
'
;
import
featuresService
from
'
../common/services/features.service
'
;
import
FeedStore
from
'
../common/stores/FeedStore
'
;
import
{
isNetworkFail
}
from
'
../common/helpers/abortableFetch
'
;
/**
* Channel Feed store
...
...
@@ -124,8 +108,8 @@ export default class ChannelFeedStore {
@
action
async
refresh
()
{
//ignore refresh on rewards view
if
(
this
.
filter
==
'
rewards
'
)
{
//
ignore refresh on rewards
or requests
view
if
(
this
.
filter
==
'
rewards
'
||
this
.
filter
==
'
request
'
)
{
return
;
}
...
...
@@ -142,6 +126,8 @@ export default class ChannelFeedStore {
setFilter
(
filter
)
{
this
.
filter
=
filter
;
if
(
filter
==
'
requests
'
||
filter
==
'
rewards
'
)
return
;
this
.
feedStore
.
setEndpoint
(
`api/v2/
${
this
.
endpoint
}
/
${
this
.
guid
}
/
${
this
.
esFeedfilter
}
`
)
.
setIsTiled
(
filter
===
'
images
'
||
filter
===
'
videos
'
)
.
clear
()
...
...
src/channel/ChannelScreen.js
View file @
ec1cafd9
...
...
@@ -4,7 +4,6 @@ import React, {
import
{
StyleSheet
,
FlatList
,
Text
,
View
,
Alert
,
...
...
@@ -18,7 +17,6 @@ import {
import
{
Icon
}
from
'
react-native-elements
'
import
RewardsCarousel
from
'
./carousel/RewardsCarousel
'
;
import
ChannelHeader
from
'
./header/ChannelHeader
'
;
import
Toolbar
from
'
./toolbar/Toolbar
'
;
import
CenteredLoading
from
'
../common/components/CenteredLoading
'
;
...
...
@@ -35,12 +33,14 @@ import { GOOGLE_PLAY_STORE } from '../config/Config';
import
i18n
from
'
../common/services/i18n.service
'
;
import
FeedList
from
'
../common/components/FeedList
'
;
import
{
FLAG_VIEW
}
from
'
../common/Permissions
'
;
import
SubscriptionButton
from
'
./subscription/SubscriptionButton
'
;
import
SubscriptionRequestList
from
'
./subscription/SubscriptionRequestList
'
;
/**
* Channel Screen
*/
export
default
@
inject
(
'
channel
'
)
@
inject
(
'
channel
'
,
'
subscriptionRequest
'
)
@
observer
class
ChannelScreen
extends
Component
{
...
...
@@ -135,7 +135,7 @@ class ChannelScreen extends Component {
*/
checkCanView
(
channel
)
{
// if the channel obj doesn't have the permissions loaded return true
if
(
!
channel
.
permissions
.
permissions
)
{
if
(
channel
.
isClosed
()
||
!
channel
.
permissions
.
permissions
)
{
return
true
}
...
...
@@ -185,6 +185,62 @@ class ChannelScreen extends Component {
this
.
props
.
navigation
.
navigate
(
'
Capture
'
);
}
getHeader
(
store
)
{
const
feed
=
store
.
feedStore
;
const
channel
=
store
.
channel
;
const
rewards
=
store
.
rewards
;
const
showClosed
=
channel
.
isClosed
()
&&
!
channel
.
subscribed
;
return
(
<
View
>
<
ChannelHeader
styles
=
{
styles
}
store
=
{
store
}
navigation
=
{
this
.
props
.
navigation
}
/
>
{
!
channel
.
blocked
&&
!
showClosed
&&
<
Toolbar
feed
=
{
feed
}
subscriptionRequest
=
{
this
.
props
.
subscriptionRequest
}
channel
=
{
channel
}
hasRewards
=
{
rewards
.
merged
&&
rewards
.
merged
.
length
}
/
>
}
{
!!
channel
.
blocked
&&
<
View
style
=
{
styles
.
blockView
}
>
<
Text
style
=
{
styles
.
blockText
}
>
{
i18n
.
t
(
'
channel.blocked
'
,{
username
:
channel
.
username
})}
<
/Text
>
<
Touchable
onPress
=
{
this
.
toggleBlock
}
>
<
Text
style
=
{
styles
.
blockTextLink
}
>
{
i18n
.
t
(
'
channel.tapUnblock
'
)}
<
/Text
>
<
/Touchable
>
<
/View
>
}
{
!!
showClosed
&&
!
channel
.
blocked
&&
<
View
style
=
{
styles
.
blockView
}
>
<
Text
style
=
{
styles
.
blockText
}
>
{
i18n
.
t
(
'
channel.isClosed
'
)}
<
/Text
>
<
SubscriptionButton
channel
=
{
channel
}
/
>
<
/View
>
}
<
/View
>
);
}
/**
* Toggle block channel
*/
toggleBlock
=
()
=>
{
this
.
props
.
channel
.
store
(
this
.
guid
).
channel
.
toggleBlock
();
}
/**
* Nav to prev screen
*/
goBack
=
()
=>
{
this
.
props
.
navigation
.
goBack
();
}
/**
* Render
*/
...
...
@@ -210,18 +266,9 @@ class ChannelScreen extends Component {
const
rewards
=
store
.
rewards
;
const
guid
=
this
.
guid
;
const
isOwner
=
guid
==
session
.
guid
;
const
isClosed
=
channel
.
isClosed
()
&&
!
channel
.
subscribed
;
let
emptyMessage
=
null
;
let
carousel
=
null
;
// carousel only visible if we have data
/*if (rewards.merged && rewards.merged.length && channelfeed.showrewards) {
carousel = (
<View style={styles.carouselcontainer}>
<RewardsCarousel rewards={rewards.merged} />
</View>
);
}*/
if
(
channel
.
is_mature
&&
!
channel
.
mature_visibility
)
{
return
(
...
...
@@ -245,31 +292,9 @@ class ChannelScreen extends Component {
}
// channel header
const
header
=
(
<
View
>
<
ChannelHeader
styles
=
{
styles
}
store
=
{
store
}
navigation
=
{
this
.
props
.
navigation
}
/
>
const
header
=
this
.
getHeader
(
store
);
{
!
channel
.
blocked
&&
<
Toolbar
feed
=
{
feed
}
hasRewards
=
{
rewards
.
merged
&&
rewards
.
merged
.
length
}
/>
}
{
carousel
}
<
SafeAreaView
style
=
{
styles
.
gobackicon
}
>
<
Icon
raised
color
=
{
colors
.
primary
}
size
=
{
22
}
name
=
'
arrow-back
'
onPress
=
{()
=>
this
.
props
.
navigation
.
goBack
()}
/
>
<
/SafeAreaView
>
{
!!
channel
.
blocked
&&
<
View
style
=
{
styles
.
blockView
}
>
<
Text
style
=
{
styles
.
blockText
}
>
{
i18n
.
t
(
'
channel.blocked
'
,{
username
:
channel
.
username
})}
<
/Text
>
<
Touchable
onPress
=
{()
=>
this
.
props
.
channel
.
store
(
this
.
guid
).
toggleBlock
()}
>
<
Text
style
=
{
styles
.
blockTextLink
}
>
{
i18n
.
t
(
'
channel.tapUnblock
'
)}
<
/Text
>
<
/Touchable
>
<
/View>
}
<
/View
>
);
let
renderActivity
=
null
let
renderActivity
=
null
,
body
=
null
;
// is a blog? use blog card to render
if
(
feed
.
filter
==
'
blogs
'
)
{
...
...
@@ -290,29 +315,25 @@ class ChannelScreen extends Component {
);
}
const
emptyRender
=
()
=>
<
View
/>
;
body
=
feed
.
filter
!=
'
requests
'
?
<
FeedList
feedStore
=
{
feed
.
feedStore
}
renderActivity
=
{
renderActivity
}
header
=
{
header
}
navigation
=
{
this
.
props
.
navigation
}
emptyMessage
=
{
emptyMessage
}
/>
:
<
SubscriptionRequestList
ListHeaderComponent
=
{
header
}
style
=
{[
CommonStyle
.
flexContainer
]}
/
>
return
(
<
View
style
=
{
CommonStyle
.
flexContainer
}
>
{
!
channel
.
blocked
&&
<
FeedList
feedStore
=
{
feed
.
feedStore
}
renderActivity
=
{
renderActivity
}
header
=
{
header
}
navigation
=
{
this
.
props
.
navigation
}
emptyMessage
=
{
emptyMessage
}
/>
}
{
/* Not using FlatList breaks header layout */
}
{
channel
.
blocked
&&
<
FlatList
style
=
{{
flex
:
1
,
backgroundColor
:
'
#fff
'
}}
ListHeaderComponent
=
{
header
}
data
=
{[]}
renderItem
=
{
emptyRender
}
/>
}
{
(
!
channel
.
blocked
&&
!
isClosed
)
?
body
:
header
}
<
SafeAreaView
style
=
{
styles
.
gobackicon
}
>
<
Icon
raised
color
=
{
colors
.
primary
}
size
=
{
22
}
name
=
'
arrow-back
'
onPress
=
{
this
.
goBack
}
/
>
<
/SafeAreaView
>
<
CaptureFab
navigation
=
{
this
.
props
.
navigation
}
/
>
<
/View
>
);
...
...
src/channel/ChannelStore.js
View file @
ec1cafd9
...
...
@@ -72,19 +72,6 @@ export default class ChannelStore {
return
false
;
}
@
action
toggleBlock
()
{
let
value
=
!
this
.
channel
.
blocked
;
return
channelService
.
toggleBlock
(
this
.
channel
.
guid
,
value
)
.
then
(
response
=>
{
this
.
channel
.
blocked
=
value
;
})
.
catch
(
err
=>
{
this
.
channel
.
blocked
=
!
value
;
logService
.
exception
(
'
[ChannelStore] toggleBlock
'
,
err
);
});
}
@
action
loadrewards
(
guid
)
{
wireService
.
rewards
(
guid
)
...
...
src/channel/UserModel.js
View file @
ec1cafd9
...
...
@@ -4,7 +4,12 @@ import api from '../common/services/api.service';
import
BaseModel
from
'
../common/BaseModel
'
;
import
ChannelService
from
'
./ChannelService
'
;
import
sessionService
from
'
../common/services/session.service
'
;
import
apiService
from
'
../common/services/api.service
'
;
import
logService
from
'
../common/services/log.service
'
;
export
const
USER_MODE_OPEN
=
0
;
export
const
USER_MODE_MODERATED
=
1
;
export
const
USER_MODE_CLOSED
=
2
;
/**
* User model
...
...
@@ -12,29 +17,35 @@ import sessionService from '../common/services/session.service';
export
default
class
UserModel
extends
BaseModel
{
/**
* @var boolean
* @var
{
boolean
}
*/
@
observable
blocked
;
/**
* @var
integ
er
* @var
{numb
er
}
*/
@
observable
subscribers_count
;
/**
* @var
integ
er
* @var
{numb
er
}
*/
@
observable
impressions
;
/**
* @var boolean
* @var
{
boolean
}
*/
@
observable
subscribed
;
/**
* @var boolean
* @var
{
boolean
}
*/
@
observable
mature_visibility
=
false
;
/**
* @var {boolean}
*/
@
observable
pending_subscribe
=
false
;
getOwnerIcontime
()
{
if
(
sessionService
.
getUser
().
guid
===
this
.
guid
)
{
return
sessionService
.
getUser
().
icontime
;
...
...
@@ -64,6 +75,19 @@ export default class UserModel extends BaseModel {
}
}
@
action
async
toggleBlock
(
value
=
null
)
{
value
=
(
value
===
null
)
?
!
this
.
blocked
:
value
;
try
{
await
ChannelService
.
toggleBlock
(
this
.
guid
,
value
);
this
.
blocked
=
value
;
}
catch
(
err
)
{
this
.
blocked
=
!
value
;
logService
.
exception
(
'
[ChannelStore] toggleBlock
'
,
err
);
}
}
/**
* Is admin
*/
...
...
@@ -83,7 +107,6 @@ export default class UserModel extends BaseModel {
* @param {string} size
*/
getBannerSource
(
size
=
'
medium
'
)
{
if
(
this
.
carousels
)
{
return
{
uri
:
this
.
carousels
[
0
].
src
...
...
@@ -102,8 +125,69 @@ export default class UserModel extends BaseModel {
/**
* Has banner
* @returns {boolean}
*/
hasBanner
()
{
return
!!
this
.
carousels
;
}
/**
* Is closed
* @returns {boolean}
*/
isClosed
()
{
return
this
.
mode
===
USER_MODE_CLOSED
;
}
/**
* Is open
* @returns {boolean}
*/
isOpen
()
{
return
this
.
mode
===
USER_MODE_OPEN
;
}
/**
* Is moderated
* @returns {boolean}
*/
isModerated
()
{
return
this
.
mode
===
USER_MODE_MODERATED
;
}
/**
* Is subscribed
* @returns {boolean}
*/
isSubscribed
()
{
return
!!
this
.
subscribed
;
}
/**
* Request subscribe
*/
async
subscribeRequest
()
{
if
(
this
.
pending_subscribe
||
this
.
mode
!==
USER_MODE_CLOSED
)
return
;
try
{
this
.
pending_subscribe
=
true
;
await
apiService
.
put
(
`api/v2/subscriptions/outgoing/
${
this
.
guid
}
`
);
}
catch
(
err
)
{
this
.
pending_subscribe
=
false
;
logService
.
exception
(
err
);
}
}
/**
* Cancel subscribe request
*/
async
cancelSubscribeRequest
()
{
if
(
!
this
.
pending_subscribe
||
this
.
mode
!==
USER_MODE_CLOSED
)
return
;
try
{
this
.
pending_subscribe
=
false
;
await
apiService
.
delete
(
`api/v2/subscriptions/outgoing/
${
this
.
guid
}
`
);
}
catch
(
err
)
{
this
.
pending_subscribe
=
true
;
logService
.
exception
(
err
);
}
}
}
\ No newline at end of file
src/channel/subscription/SubscriptionButton.js
0 → 100644
View file @
ec1cafd9
// @flow
import
React
,
{
Component
}
from
'
react
'
;
import
{
Alert
}
from
'
react-native
'
;
import
type
{
Node
}
from
'
react
'
;
import
{
observer
}
from
'
mobx-react
'
;
import
type
UserModel
from
'
../UserModel
'
;
import
Button
from
'
../../common/components/Button
'
;
import
i18n
from
'
../../common/services/i18n.service
'
;
import
Icon
from
'
react-native-vector-icons/Ionicons
'
;
import
{
CommonStyle
}
from
'
../../styles/Common
'
;
type
PropsType
=
{
channel
:
UserModel
};
/**
* Subscription request
*/
export
default
@
observer
class
SubscriptionButton
extends
Component
<
PropsType
>
{
/**
* On press
*/
onPress
=
()
=>
{
const
{
channel
}
=
this
.
props
;
if
(
channel
.
isOpen
()
||
channel
.
subscribed
)
{
if
(
channel
.
subscribed
)
{
Alert
.
alert
(
i18n
.
t
(
'
attention
'
),
i18n
.
t
(
'
channel.confirmUnsubscribe
'
),
[{
text
:
i18n
.
t
(
'
yesImSure
'
),
onPress
:
()
=>
channel
.
toggleSubscription
()
},
{
text
:
i18n
.
t
(
'
no
'
)}]
);
}
else
{
channel
.
toggleSubscription
();
}
}
else
if
(
channel
.
pending_subscribe
)
{
channel
.
cancelSubscribeRequest
();
}
else
{
channel
.
subscribeRequest
();
}
}
/**
* Render
*/
render
():
Node
{
const
{
channel
,
...
otherProps
}
=
this
.
props
;
let
text
,
icon
=
null
;
if
(
channel
.
isOpen
())
{
text
=
channel
.
subscribed
?
i18n
.
t
(
'
channel.unsubscribe
'
)
:
i18n
.
t
(
'
channel.subscribe
'
);
}
else
{
text
=
channel
.
subscribed
?
i18n
.
t
(
'
channel.unsubscribe
'
)
:
(
!
channel
.
pending_subscribe
?
i18n
.
t
(
'
channel.requestSubscription
'
)
:
i18n
.
t
(
'
pending
'
));
if
(
channel
.
pending_subscribe
)
{
icon
=
<
Icon
name
=
"
ios-close
"
style
=
{[
CommonStyle
.
colorPrimary
,
CommonStyle
.
paddingLeft
]}
size
=
{
23
}
/
>
}
}
return
(
<
Button
text
=
{
text
}
onPress
=
{
this
.
onPress
}
{...
otherProps
}
>
{
icon
}
<
/Button
>
)
}
}
src/channel/subscription/SubscriptionRequest.js
0 → 100644
View file @
ec1cafd9
// @flow
import
React
from
'
react
'
;
import
{
View
,
Text
}
from
'
react-native
'
;
import
type
{
Node
}
from
'
react
'
;
import
type
UserModel
from
'
../UserModel
'
;
import
type
SubscriptionRequestStore
from
'
./SubscriptionRequestStore
'
;
import
DiscoveryUser
from
'
../../discovery/DiscoveryUser
'
;
import
Button
from
'
../../common/components/Button
'
;
import
i18nService
from
'
../../common/services/i18n.service
'
;
import
{
CommonStyle
as
CS
}
from
'
../../styles/Common
'
;
import
{
observer
}
from
'
mobx-react
'
;
type
PropsType
=
{
row
:
any
,
subscriptionRequest
:
SubscriptionRequestStore
};
/**
* Subscription Request
*/
export
default
@
observer
class
SubscriptionRequest
extends
DiscoveryUser
<
PropsType
>
{
/**
* Get the channel from the props
*/
getChannel
():
UserModel
{
return
this
.
props
.
row
.
item
.
subscriber
;
}
/**
* Accept the request
*/
onAccept
=
()
=>
{
this
.
props
.
subscriptionRequest
.
accept
(
this
.
props
.
row
.
item
)
}
/**
* reject the request
*/
onReject
=
()
=>
{
this
.
props
.
subscriptionRequest
.
decline
(
this
.
props
.
row
.
item
)
}
/**
* Render Right buttons
*/
renderRightButton
():
Node
{
if
(
this
.
props
.
row
.
item
.
status
)
{
return
(
<
View
style
=
{[
CS
.
rowJustifyEnd
]}
>
<
Text
style
=
{[
this
.
props
.
row
.
item
.
status
!=
'
requestAccepted
'
?
CS
.
colorDanger
:
CS
.
colorPrimary
]}
>
{
i18nService
.
t
(
`channel.
${
this
.
props
.
row
.
item
.
status
}
`
)}
<
/Text
>
<
/View
>
)
}
return
(
<
View
style
=
{[
CS
.
rowJustifyEnd
]}
>
<
Button
text
=
{
i18nService
.
t
(
'
accept
'
)}
onPress
=
{
this
.
onAccept
}
loading
=
{
this
.
props
.
row
.
item
.
inProgress
}
inverted
/>
<
Button
text
=
{
i18nService
.
t
(
'
reject
'
)}
loading
=
{
this
.
props
.
row
.
item
.
inProgress
}
onPress
=
{
this
.
onReject
}
/
>
<
/View
>
)
}
}
src/channel/subscription/SubscriptionRequestList.js
0 → 100644
View file @
ec1cafd9
// @flow
import
React
,
{
Component
}
from
'
react
'
;
import
{
FlatList
,
ActivityIndicator
,
Text
,
View
}
from
'
react-native
'
;
import
type
{
Node
,
Element
}
from
'
react
'
;
import
type
SubscriptionRequestStore
from
'
./SubscriptionRequestStore
'
;
import
{
inject
,
observer
}
from
'
mobx-react/native
'
;
import
SubscriptionRequest
from
'
./SubscriptionRequest
'
;
import
i18n
from
'
../../common/services/i18n.service
'
;
import
{
CommonStyle
as
CS
}
from
'
../../styles/Common
'
;
import
ErrorLoading
from
'
../../common/components/ErrorLoading
'
;
type
PropsType
=
{
subscriptionRequest
:
SubscriptionRequestStore
};
/**
* Subscription list
*/
export
default
@
inject
(
'
subscriptionRequest
'
)
@
observer
class
SubscriptionRequestList
extends
Component
<
PropsType
>
{
/**
* Render item
*/
renderItem
=
(
row
:
any
):
Element
<
any
>
=>
{
return
(
<
SubscriptionRequest
row
=
{
row
}
onAccept
=
{
this
.
onAccept
}
onReject
=
{
this
.
onReject
}
subscriptionRequest
=
{
this
.
props
.
subscriptionRequest
}
/
>
)
}
onAccept
=
(
row
:
any
)
=>
{
}
onReject
=
(
row
:
any
)
=>
{
}
reload
=
()
=>
{
this
.
props
.
subscriptionRequest
.
load
();
}
/**
* Render
*/
render
():
Node
{
const
{
subscriptionRequest
,
...
otherProps
}
=
this
.
props
;
let
footerCmp
=
null
,
emptyCmp
=
null
;
if
(
subscriptionRequest
.
errorLoading
)
{
footerCmp
=
<
ErrorLoading
message
=
{
i18n
.
t
(
'
cantLoad
'
)}
tryAgain
=
{
this
.
reload
}
/
>
}
else
{
const
message
=
subscriptionRequest
.
loading
?
<
ActivityIndicator
size
=
"
large
"
/>
:
<
Text
style
=
{[
CS
.
fontM
,
CS
.
fontHairline
]}
>
{
i18n
.
t
(
'
discovery.nothingToShow
'
)}
<
/Text
>
emptyCmp
=
<
View
style
=
{[
CS
.
flexColumnCentered
,
CS
.
marginTop4x
,
CS
.
paddingTop2x
]}
>
{
message
}
<
/View
>
}
return
(
<
FlatList
data
=
{
subscriptionRequest
.
requests
}
renderItem
=
{
this
.
renderItem
}
ListEmptyComponent
=
{
emptyCmp
}
ListFooterComponent
=
{
footerCmp
}
{...
otherProps
}
/
>
)
}
}
\ No newline at end of file
src/channel/subscription/SubscriptionRequestStore.js
0 → 100644
View file @
ec1cafd9
//@flow
import
{
observable
,
action
,
extendObservable
}
from
"
mobx
"
;
import
api
from
"
../../common/services/api.service
"
;
import
logService
from
"
../../common/services/log.service
"
;
import
UserModel
from
"
../UserModel
"
;
/**
* Subscription request store
*/
export
default
class
SubscriptionRequestStore
{
@
observable
requests
=
[];
@
observable
loading
=
false
;
@
observable
errorLoading
=
false
;
/**
* Load the subscriptions requests
*/
@
action
async
load
():
Promise
<
any
>
{
this
.
setLoading
(
true
);
this
.
setErrorLoading
(
false
);
try
{
let
{
requests
}
=
await
api
.
get
(
`api/v2/subscriptions/incoming`
);
this
.
setRequest
(
requests
);
}
catch
(
err
)
{
this
.
setErrorLoading
(
true
);
logService
.
exception
(
err
);
}
finally
{
this
.
setLoading
(
false
);
}
}
/**
* Accept a request
* @param {any} request
*/
async
accept
(
request
:
any
):
Promise
<
void
>
{
try
{
this
.
setInProgress
(
request
,
true
);
await
api
.
put
(
`api/v2/subscriptions/incoming/
${
request
.
subscriber
.
guid
}
/accept`
);
this
.
setStatus
(
request
,
'
requestAccepted
'
);
}
catch
(
err
)
{
logService
.
exception
(
err
);
}
finally
{
this
.
setInProgress
(
request
,
false
);
}
}
/**
* Decline a request
* @param {any} request
*/
async
decline
(
request
:
any
):
Promise
<
void
>
{
try
{
this
.
setInProgress
(
request
,
true
);
await
api
.
put
(
`api/v2/subscriptions/incoming/
${
request
.
subscriber
.
guid
}
/decline`
);
this
.
setStatus
(
request
,
'
requestRejected
'
);
}
catch
(
err
)
{
logService
.
exception
(
err
);
}
finally
{
this
.
setInProgress
(
request
,
false
);
}
}
/**
* Set action
*/
@
action
setLoading
(
value
:
boolean
)
{
this
.
loading
=
value
;
}
/**
* Set requests list
* @param {Array<any>}
*/
@
action
setRequest
(
requests
:
Array
<
any
>
)
{
this
.
requests
=
requests
;
this
.
requests
.
forEach
((
r
:
any
):
any
=>
{
extendObservable
(
r
,
{
inProgress
:
false
,
status
:
''
});
r
.
subscriber
=
UserModel
.
create
(
r
.
subscriber
);
});
}
/**
* Set the error loading flag
* @param {boolean} value
*/
@
action
setErrorLoading
(
value
:
boolean
)
{
this
.
errorLoading
=
value
;
}
/**
* Set the in progress flag
* @param {any} request
* @param {boolean} value
*/
@
action
setInProgress
(
request
:
any
,
value
:
boolean
)
{
request
.
inProgress
=
value
;
}
/**
* Set the status flag
* @param {any} request
* @param {string} value
*/
@
action
setStatus
(
request
:
any
,
value
:
string
)
{
request
.
status
=
value
;
console
.
log
(
'
SETTNIG REQUEST
'
,
request
)
}
/**
* Clear the store to the default values
*/
@
action
clear
()
{
this
.
requests
=
[];
this
.
errorLoading
=
false
;
}
/**
* Reset the store
*/
reset
()
{
this
.
clear
();
}
}
\ No newline at end of file
src/channel/toolbar/Toolbar.js
View file @
ec1cafd9
...
...
@@ -8,19 +8,21 @@ import {
import
{
observer
,
inject
}
from
'
mobx-react/native
'
;
import
Icon
from
'
react-native-vector-icons/MaterialIcons
'
;
import
IonIcon
from
'
react-native-vector-icons/Ionicons
'
;
import
FAIcon
from
'
react-native-vector-icons/FontAwesome5
'
;
import
i18n
from
'
../../common/services/i18n.service
'
;
import
colors
from
'
../../styles/Colors
'
;
import
featuresService
from
'
../../common/services/features.service
'
;
const
ICON_SIZE
=
22
;
export
default
@
observer
export
default
class
Toolbar
extends
Component
{
class
Toolbar
extends
Component
{
filterRewards
=
()
=>
{
this
.
props
.
feed
.
setFilter
(
'
rewards
'
);
...
...
@@ -42,18 +44,32 @@ export default class Toolbar extends Component {
this
.
props
.
feed
.
setFilter
(
'
blogs
'
);
}
filterRequests
=
()
=>
{
this
.
props
.
feed
.
setFilter
(
'
requests
'
);
this
.
props
.
subscriptionRequest
.
load
();
}
render
()
{
const
filter
=
this
.
props
.
feed
.
filter
;
const
pstyles
=
this
.
props
.
styles
;
let
rewards
=
null
;
let
rewards
=
null
,
subscriptionRequests
=
null
;
if
(
this
.
props
.
hasRewards
)
{
rewards
=
(
<
TouchableOpacity
style
=
{
styles
.
button
}
onPress
=
{
this
.
filterRewards
}
>
<
IonIcon
name
=
"
ios-flash
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
rewards
'
?
colors
.
primary
:
color
}
/
>
<
Text
style
=
{
styles
.
buttontext
}
>
{
i18n
.
t
(
'
rewards
'
).
toUpperCase
()}
<
/Text
>
<
IonIcon
name
=
"
ios-flash
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
rewards
'
?
colors
.
primary
:
color
}
style
=
{
styles
.
icon
}
/
>
<
Text
style
=
{[
styles
.
buttontext
,
filter
==
'
rewards
'
?
styles
.
buttontextSelected
:
null
]}
>
{
i18n
.
t
(
'
rewards
'
).
toUpperCase
()}
<
/Text
>
<
/TouchableOpacity
>
)
}
if
(
this
.
props
.
channel
.
isOwner
()
&&
featuresService
.
has
(
'
permissions
'
))
{
subscriptionRequests
=
(
<
TouchableOpacity
style
=
{
styles
.
button
}
onPress
=
{
this
.
filterRequests
}
>
<
FAIcon
name
=
"
user-check
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
requests
'
?
colors
.
primary
:
color
}
style
=
{
styles
.
icon
}
/
>
<
Text
style
=
{[
styles
.
buttontext
,
filter
==
'
requests
'
?
styles
.
buttontextSelected
:
null
]}
>
{
i18n
.
t
(
'
requests
'
).
toUpperCase
()}
<
/Text
>
<
/TouchableOpacity
>
)
}
...
...
@@ -62,22 +78,23 @@ export default class Toolbar extends Component {
<
View
style
=
{
styles
.
container
}
>
<
View
style
=
{
styles
.
topbar
}
>
<
TouchableOpacity
style
=
{
styles
.
button
}
onPress
=
{
this
.
filterFeed
}
>
<
Icon
name
=
"
list
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
feed
'
?
colors
.
primary
:
color
}
/
>
<
Text
style
=
{
styles
.
buttontext
}
>
{
i18n
.
t
(
'
feed
'
).
toUpperCase
()}
<
/Text
>
<
Icon
name
=
"
list
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
feed
'
?
colors
.
primary
:
color
}
style
=
{
styles
.
icon
}
/
>
<
Text
style
=
{
[
styles
.
buttontext
,
filter
==
'
feed
'
?
styles
.
buttontextSelected
:
null
]
}
>
{
i18n
.
t
(
'
feed
'
).
toUpperCase
()}
<
/Text
>
<
/TouchableOpacity
>
<
TouchableOpacity
style
=
{
styles
.
button
}
onPress
=
{
this
.
filterImages
}
>
<
IonIcon
name
=
"
md-image
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
images
'
?
colors
.
primary
:
color
}
/
>
<
Text
style
=
{
styles
.
buttontext
}
>
{
i18n
.
t
(
'
images
'
).
toUpperCase
()}
<
/Text
>
<
IonIcon
name
=
"
md-image
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
images
'
?
colors
.
primary
:
color
}
style
=
{
styles
.
icon
}
/
>
<
Text
style
=
{
[
styles
.
buttontext
,
filter
==
'
images
'
?
styles
.
buttontextSelected
:
null
]
}
>
{
i18n
.
t
(
'
images
'
).
toUpperCase
()}
<
/Text
>
<
/TouchableOpacity
>
<
TouchableOpacity
style
=
{
styles
.
button
}
onPress
=
{
this
.
filterVideos
}
>
<
IonIcon
name
=
"
md-videocam
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
videos
'
?
colors
.
primary
:
color
}
/
>
<
Text
style
=
{
styles
.
buttontext
}
>
{
i18n
.
t
(
'
videos
'
).
toUpperCase
()}
<
/Text
>
<
IonIcon
name
=
"
md-videocam
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
videos
'
?
colors
.
primary
:
color
}
style
=
{
styles
.
icon
}
/
>
<
Text
style
=
{
[
styles
.
buttontext
,
filter
==
'
videos
'
?
styles
.
buttontextSelected
:
null
]
}
>
{
i18n
.
t
(
'
videos
'
).
toUpperCase
()}
<
/Text
>
<
/TouchableOpacity
>
<
TouchableOpacity
style
=
{
styles
.
button
}
onPress
=
{
this
.
filterBlogs
}
>
<
Icon
name
=
"
subject
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
blogs
'
?
colors
.
primary
:
color
}
/
>
<
Text
style
=
{
styles
.
buttontext
}
>
{
i18n
.
t
(
'
blogs.blogs
'
).
toUpperCase
()}
<
/Text
>
<
Icon
name
=
"
subject
"
size
=
{
ICON_SIZE
}
color
=
{
filter
==
'
blogs
'
?
colors
.
primary
:
color
}
style
=
{
styles
.
icon
}
/
>
<
Text
style
=
{
[
styles
.
buttontext
,
filter
==
'
blogs
'
?
styles
.
buttontextSelected
:
null
]
}
>
{
i18n
.
t
(
'
blogs.blogs
'
).
toUpperCase
()}
<
/Text
>
<
/TouchableOpacity
>
{
rewards
}
{
subscriptionRequests
}
<
/View
>
<
/View
>
);
...
...
@@ -88,17 +105,21 @@ const color = '#444'
const
styles
=
StyleSheet
.
create
({
container
:
{
height
:
6
5
,
height
:
5
5
,
display
:
'
flex
'
,
flexDirection
:
'
row
'
,
paddingTop
:
12
,
paddingTop
:
5
,
paddingLeft
:
0
,
paddingRight
:
0
,
paddingBottom
:
5
,
borderBottomWidth
:
StyleSheet
.
hairlineWidth
,
borderBottomColor
:
'
#EEE
'
,
borderTopWidth
:
StyleSheet
.
hairlineWidth
,
borderTopColor
:
'
#EEE
'
,
},
icon
:
{
height
:
25
,
},
topbar
:
{
flex
:
1
,
justifyContent
:
'
space-between
'
,
...
...
@@ -109,8 +130,12 @@ const styles = StyleSheet.create({
fontSize
:
10
,
color
:
'
#444
'
,
},
buttontextSelected
:
{
color
:
colors
.
primary
},
button
:
{
flex
:
1
,
justifyContent
:
'
space-between
'
,
flexDirection
:
'
column
'
,
alignItems
:
'
center
'
,
padding
:
3
,
...
...
src/common/BaseModel.js
View file @
ec1cafd9
...
...
@@ -227,7 +227,7 @@ export default class BaseModel {
*/
blockOwner
()
{
if
(
!
this
.
ownerObj
)
throw
new
Error
(
'
This entity has no owner
'
);
return
channelService
.
toggleBlock
(
this
.
ownerObj
.
guid
,
true
);
return
this
.
ownerObj
.
toggleBlock
(
true
);
}
/**
...
...
@@ -235,7 +235,7 @@ export default class BaseModel {
*/
unblockOwner
()
{
if
(
!
this
.
ownerObj
)
throw
new
Error
(
'
This entity has no owner
'
);
return
channelService
.
toggleBlock
(
this
.
ownerObj
.
guid
,
false
);
return
this
.
ownerObj
.
toggleBlock
(
false
);
}
@
action
...
...
src/common/components/Button.js
View file @
ec1cafd9
...
...
@@ -10,7 +10,6 @@ import {
TouchableOpacity
,
}
from
'
react-native
'
;
import
{
CommonStyle
}
from
'
../../styles/Common
'
;
import
{
ComponentsStyle
}
from
'
../../styles/Components
'
;
import
colors
from
'
../../styles/Colors
'
;
...
...
@@ -62,7 +61,7 @@ export default class Button extends Component {
const
body
=
this
.
props
.
loading
?
<
ActivityIndicator
color
=
{
mainColor
}
/>
:
<
Text
style
=
{[{
color
:
textColor
||
mainColor
},
textStyle
]}
>
{
this
.
props
.
text
}
<
/Text>
;
<
Text
style
=
{[{
color
:
textColor
||
mainColor
},
textStyle
]}
>
{
this
.
props
.
text
}
<
/Text>
;
const
onButtonPress
=
this
.
props
.
loading
?
null
:
onPress
;
...
...
src/common/services/log.service.js
View file @
ec1cafd9
...
...
@@ -76,20 +76,21 @@ class LogService {
prepend
=
null
;
}
// do not log request or api errors < 500
if
(
!
isNetworkFail
(
error
)
&&
(
!
this
.
isApiError
(
error
)
||
this
.
isUnexpectedError
(
error
)))
{
// report the issue to sentry
Sentry
.
captureException
(
error
);
}
let
stack
=
null
;
if
(
__DEV__
)
{
stack
=
parseErrorStack
(
error
);
}
if
(
stack
)
{
deviceLog
.
rnerror
(
false
,
(
prepend
?
`
${
prepend
}
`
:
''
)
+
error
.
message
,
stack
);
if
(
__DEV__
)
console
.
log
(
error
);
}
else
{
deviceLog
.
error
((
prepend
?
`
${
prepend
}
`
:
''
)
+
String
(
error
));
let
stack
=
null
;
if
(
__DEV__
)
{
stack
=
parseErrorStack
(
error
);
}
if
(
stack
)
{
deviceLog
.
rnerror
(
false
,
(
prepend
?
`
${
prepend
}
`
:
''
)
+
error
.
message
,
stack
);
if
(
__DEV__
)
console
.
log
(
error
);
}
else
{
deviceLog
.
error
((
prepend
?
`
${
prepend
}
`
:
''
)
+
String
(
error
));
}
}
}
}
...
...
src/discovery/DiscoveryScreen.js
View file @
ec1cafd9
...
...
@@ -547,7 +547,7 @@ export default class DiscoveryScreen extends Component {
return
(
<
ErrorBoundary
containerStyle
=
{
CS
.
hairLineBottom
}
>
<
DiscoveryUser
entity
=
{
row
}
navigation
=
{
this
.
props
.
navigation
}
hideButtons
=
{
this
.
props
.
discovery
.
filters
.
type
==
'
lastchannels
'
}
/
>
<
DiscoveryUser
row
=
{
row
}
navigation
=
{
this
.
props
.
navigation
}
hideButtons
=
{
this
.
props
.
discovery
.
filters
.
type
==
'
lastchannels
'
}
/
>
<
/ErrorBoundary
>
);
}
...
...
src/discovery/DiscoveryUser.js
View file @
ec1cafd9
...
...
@@ -6,33 +6,26 @@ import {
TouchableOpacity
,
Image
,
StyleSheet
,
Alert
,
Keyboard
,
TouchableHighlight
,
Text
,
View
}
from
'
react-native
'
;
import
{
observer
,
inject
}
from
'
mobx-react/native
'
import
{
MINDS_CDN_URI
}
from
'
../config/Config
'
;
import
abbrev
from
'
../common/helpers/abbrev
'
import
colors
from
'
../styles/Colors
'
import
{
ComponentsStyle
}
from
'
../styles/Components
'
;
import
{
CommonStyle
}
from
'
../styles/Common
'
;
import
i18n
from
'
../common/services/i18n.service
'
;
import
{
FLAG_SUBSCRIBE
,
FLAG_VIEW
}
from
'
../common/Permissions
'
;
import
SubscriptionButton
from
'
../channel/subscription/SubscriptionButton
'
;
@
inject
(
'
user
'
)
export
default
@
observer
export
default
class
DiscoveryUser
extends
Component
{
class
DiscoveryUser
extends
Component
{
/**
* Navigate To channel
...
...
@@ -40,61 +33,35 @@ export default class DiscoveryUser extends Component {
_navToChannel
=
()
=>
{
Keyboard
.
dismiss
();
if
(
this
.
props
.
navigation
)
{
if
(
!
this
.
props
.
entity
.
item
.
can
(
FLAG_VIEW
,
true
))
{
if
(
this
.
props
.
row
.
item
.
isOpen
()
&&
!
this
.
props
.
row
.
item
.
can
(
FLAG_VIEW
,
true
))
{
return
;
}
this
.
props
.
navigation
.
push
(
'
Channel
'
,
{
entity
:
this
.
props
.
entity
.
item
});
}
}
toggleSubscribe
=
()
=>
{
if
(
this
.
props
.
entity
.
item
.
subscribed
)
{
Alert
.
alert
(
i18n
.
t
(
'
attention
'
),
i18n
.
t
(
'
channel.confirmUnsubscribe
'
),
[{
text
:
i18n
.
t
(
'
yesImSure
'
),
onPress
:
()
=>
this
.
_toggleSusbcribed
()
},
{
text
:
i18n
.
t
(
'
no
'
)}]
);
}
else
{
this
.
_toggleSusbcribed
();
this
.
props
.
navigation
.
push
(
'
Channel
'
,
{
entity
:
this
.
props
.
row
.
item
});
}
}
_toggleSusbcribed
()
{
const
item
=
this
.
props
.
entity
.
item
;
this
.
props
.
entity
.
item
.
toggleSubscription
();
}
renderRightButton
()
{
const
item
=
this
.
props
.
entity
.
item
;
if
(
this
.
props
.
user
.
me
.
guid
===
item
.
guid
||
this
.
props
.
hideButtons
||
!
item
.
can
(
FLAG_SUBSCRIBE
))
{
const
channel
=
this
.
props
.
row
.
item
;
if
(
channel
.
isOwner
()
||
this
.
props
.
hideButtons
||
(
channel
.
isOpen
()
&&
!
channel
.
can
(
FLAG_SUBSCRIBE
)
))
{
return
;
}
if
(
item
.
subscribed
)
{
return
<
TouchableHighlight
onPress
=
{
this
.
toggleSubscribe
}
underlayColor
=
'
transparent
'
style
=
{[
ComponentsStyle
.
button
]}
accessibilityLabel
=
{
i18n
.
t
(
'
channel.subscribeMessage
'
)}
>
<
Text
style
=
{{
color
:
'
#888
'
}}
>
{
i18n
.
t
(
'
channel.subscribed
'
)}
<
/Text
>
<
/TouchableHighlight>
;
}
else
{
return
<
TouchableHighlight
onPress
=
{
this
.
toggleSubscribe
}
underlayColor
=
'
transparent
'
style
=
{[
ComponentsStyle
.
button
,
ComponentsStyle
.
buttonAction
]}
accessibilityLabel
=
{
i18n
.
t
(
'
channel.unsubscribeMessage
'
)}
>
<
Text
style
=
{{
color
:
colors
.
primary
}}
>
{
i18n
.
t
(
'
channel.subscribe
'
)}
<
/Text
>
<
/TouchableHighlight>
;
}
return
(
<
SubscriptionButton
channel
=
{
channel
}
/
>
)
}
getChannel
()
{
return
this
.
props
.
row
.
item
;
}
/**
* Render
*/
render
()
{
const
item
=
this
.
props
.
entity
.
item
;
const
item
=
this
.
getChannel
()
;
const
avatarImg
=
{
uri
:
MINDS_CDN_URI
+
'
icon/
'
+
item
.
guid
+
'
/medium
'
};
return
(
<
TouchableOpacity
style
=
{
styles
.
row
}
onPress
=
{
this
.
_navToChannel
}
>
...
...
src/groups/GroupUser.js
View file @
ec1cafd9
import
React
,
{
Component
}
from
'
react
'
;
import
React
from
'
react
'
;
import
{
StyleSheet
}
from
'
react-native
'
;
import
{
observer
,
inject
}
from
'
mobx-react/native
'
import
Icon
from
'
react-native-vector-icons/MaterialIcons
'
;
import
DiscoveryUser
from
'
../discovery/DiscoveryUser
'
;
...
...
@@ -18,24 +12,24 @@ import DiscoveryUser from '../discovery/DiscoveryUser';
/**
* Group user component
*/
@
inject
(
'
user
'
)
export
default
class
GroupUser
extends
DiscoveryUser
.
wrappedComponent
{
export
default
class
GroupUser
extends
DiscoveryUser
{
/**
* Handle right button press
*/
handlePress
=
()
=>
{
this
.
props
.
onRightIconPress
(
this
.
props
.
entity
.
item
)
this
.
props
.
onRightIconPress
(
this
.
props
.
row
.
item
)
}
/**
* Render right button
*/
renderRightButton
()
{
const
item
=
this
.
props
.
entity
.
item
;
const
item
=
this
.
props
.
row
.
item
;
if
(
!
(
this
.
props
.
isOwner
||
this
.
props
.
isModerator
)
||
this
.
props
.
user
.
me
.
guid
===
item
.
guid
||
this
.
props
.
isModerator
&&
this
.
props
.
entity
.
item
[
'
is:owner
'
])
{
item
.
isOwner
()
||
this
.
props
.
isModerator
&&
this
.
props
.
row
.
item
[
'
is:owner
'
])
{
return
;
}
...
...
src/groups/card/GroupCard.js
View file @
ec1cafd9
...
...
@@ -9,8 +9,6 @@ import {
StyleSheet
,
}
from
'
react-native
'
;
import
Icon
from
'
react-native-vector-icons/Ionicons
'
;
import
{
MINDS_CDN_URI
}
from
'
../../config/Config
'
;
import
abbrev
from
'
../../common/helpers/abbrev
'
;
import
FastImage
from
'
react-native-fast-image
'
;
...
...
src/styles/Components.js
View file @
ec1cafd9
...
...
@@ -67,11 +67,13 @@ export const ComponentsStyle = StyleSheet.create({
//button
commonButton
:
{
margin
:
4
,
padding
:
4
,
alignItems
:
'
center
'
,
borderRadius
:
20
,
borderWidth
:
1
,
flexDirection
:
'
row
'
,
justifyContent
:
'
center
'
,
margin
:
4
,
padding
:
4
,
},
bluebutton
:
{
margin
:
4
,
...
...