Skip to content
Next
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
Minds Mobile
Project
Project
Details
Activity
Releases
Cycle Analytics
Insights
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Issues
191
Issues
191
List
Boards
Labels
Service Desk
Milestones
Merge Requests
15
Merge Requests
15
Security & Compliance
Security & Compliance
Dependency List
Packages
Packages
List
Container Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Minds
Minds Mobile
Compare Revisions
ba34258c5c1b91c48c52d109758f1d80380abeaa...ec1cafd917203e4554ce083a1e4e8bc505df7710
Source
ec1cafd917203e4554ce083a1e4e8bc505df7710
Select Git revision
...
Target
ba34258c5c1b91c48c52d109758f1d80380abeaa
Select Git revision
Compare
Commits (5)
(feat) add open/close logic to UserModel
· b854aa6d
Martin Santangelo
authored
10 hours ago
b854aa6d
(fix) invariant violation Text strings must be rendered within a Text component
· b43773c8
Martin Santangelo
authored
10 hours ago
b43773c8
(feat) implement open/closed channel
· 69d92731
Martin Santangelo
authored
42 minutes ago
69d92731
(feat) do not log network fail, aborts, etc
· 1892c2ed
Martin Santangelo
authored
42 minutes ago
1892c2ed
(chore) remove unused import
· ec1cafd9
Martin Santangelo
authored
41 minutes ago
ec1cafd9
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
657 additions
and
200 deletions
+657
-200
AppStores.js
AppStores.js
+2
-0
locales/en.json
locales/en.json
+6
-1
src/channel/ChannelActions.js
src/channel/ChannelActions.js
+8
-6
src/channel/ChannelFeedStore.js
src/channel/ChannelFeedStore.js
+4
-18
src/channel/ChannelScreen.js
src/channel/ChannelScreen.js
+79
-58
src/channel/ChannelStore.js
src/channel/ChannelStore.js
+0
-13
src/channel/UserModel.js
src/channel/UserModel.js
+90
-6
src/channel/subscription/SubscriptionButton.js
src/channel/subscription/SubscriptionButton.js
+79
-0
src/channel/subscription/SubscriptionRequest.js
src/channel/subscription/SubscriptionRequest.js
+77
-0
src/channel/subscription/SubscriptionRequestList.js
src/channel/subscription/SubscriptionRequestList.js
+92
-0
src/channel/subscription/SubscriptionRequestStore.js
src/channel/subscription/SubscriptionRequestStore.js
+136
-0
src/channel/toolbar/Toolbar.js
src/channel/toolbar/Toolbar.js
+40
-15
src/common/BaseModel.js
src/common/BaseModel.js
+2
-2
src/common/components/Button.js
src/common/components/Button.js
+1
-2
src/common/services/log.service.js
src/common/services/log.service.js
+11
-10
src/discovery/DiscoveryScreen.js
src/discovery/DiscoveryScreen.js
+1
-1
src/discovery/DiscoveryUser.js
src/discovery/DiscoveryUser.js
+18
-51
src/groups/GroupUser.js
src/groups/GroupUser.js
+7
-13
src/groups/card/GroupCard.js
src/groups/card/GroupCard.js
+0
-2
src/styles/Components.js
src/styles/Components.js
+4
-2
No files found.
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
(),
...
...
This diff is collapsed.
Click to expand it.
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"
}
This diff is collapsed.
Click to expand it.
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
.
subscribed
){
if
(
this
.
props
.
store
.
channel
.
isSubscribed
()
){
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
.
subscribed
&&
channel
.
can
(
FLAG_SUBSCRIBE
);
const
showMessage
=
!
isOwner
&&
channel
.
subscribed
&&
channel
.
can
(
FLAG_MESSAGE
);
const
showSubscribe
=
!
isOwner
&&
!
channel
.
isSubscribed
()
&&
channel
.
can
(
FLAG_SUBSCRIBE
);
const
showMessage
=
!
isOwner
&&
channel
.
isSubscribed
()
&&
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
.
ActionSheet
=
o
}
ref
=
{
this
.
setSheetRef
}
title
=
{
i18n
.
t
(
'
actions
'
)}
options
=
{
this
.
getOptions
()}
onPress
=
{
this
.
handleSelection
}
...
...
This diff is collapsed.
Click to expand it.
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 reward
s view
if
(
this
.
filter
==
'
rewards
'
)
{
//
ignore refresh on rewards or request
s 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
()
...
...
This diff is collapsed.
Click to expand it.
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
>
);
...
...
This diff is collapsed.
Click to expand it.
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
)
...
...
This diff is collapsed.
Click to expand it.
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
integer
* @var
{number}
*/
@
observable
subscribers_count
;
/**
* @var
integer
* @var
{number}
*/
@
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
This diff is collapsed.
Click to expand it.
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
>
)
}
}
This diff is collapsed.
Click to expand it.
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
>
)
}
}
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
,
...
...
This diff is collapsed.
Click to expand it.
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
...
...
This diff is collapsed.
Click to expand it.
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
;
...
...
This diff is collapsed.
Click to expand it.
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
));
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
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
>
);
}
...
...
This diff is collapsed.
Click to expand it.
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
}
>
...
...
This diff is collapsed.
Click to expand it.
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
;
}
...
...
This diff is collapsed.
Click to expand it.
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
'
;
...
...
This diff is collapsed.
Click to expand it.
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
,
...
...
This diff is collapsed.
Click to expand it.