esoftplay 0.0.113-a → 0.0.113-b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/build.js +0 -2
- package/modules/{content → lib}/gallery.tsx +3 -3
- package/modules/{content → lib}/video.tsx +3 -3
- package/package.json +1 -1
- package/modules/content/audio.tsx +0 -126
- package/modules/content/bookmark.tsx +0 -81
- package/modules/content/category.tsx +0 -59
- package/modules/content/category_list.tsx +0 -52
- package/modules/content/comment.tsx +0 -173
- package/modules/content/comment_item.tsx +0 -60
- package/modules/content/config.tsx +0 -79
- package/modules/content/detail.tsx +0 -150
- package/modules/content/header.tsx +0 -49
- package/modules/content/index.tsx +0 -52
- package/modules/content/item.tsx +0 -112
- package/modules/content/item_header.tsx +0 -59
- package/modules/content/list.tsx +0 -60
- package/modules/content/search.tsx +0 -37
package/bin/build.js
CHANGED
|
@@ -271,7 +271,6 @@ export default function App() {
|
|
|
271
271
|
'@react-navigation/native',
|
|
272
272
|
'@react-navigation/stack',
|
|
273
273
|
'buffer',
|
|
274
|
-
'expo-av',
|
|
275
274
|
'expo-application',
|
|
276
275
|
'expo-camera',
|
|
277
276
|
'expo-clipboard',
|
|
@@ -282,7 +281,6 @@ export default function App() {
|
|
|
282
281
|
'expo-font',
|
|
283
282
|
'expo-image-manipulator',
|
|
284
283
|
'expo-image-picker',
|
|
285
|
-
'expo-linear-gradient',
|
|
286
284
|
'expo-media-library',
|
|
287
285
|
'expo-notifications',
|
|
288
286
|
'expo-status-bar',
|
|
@@ -5,13 +5,13 @@ import React, { useRef } from 'react';
|
|
|
5
5
|
import { Pressable, View } from 'react-native';
|
|
6
6
|
import Gallery from 'react-native-awesome-gallery';
|
|
7
7
|
|
|
8
|
-
export interface
|
|
8
|
+
export interface LibGalleryArgs {
|
|
9
9
|
|
|
10
10
|
}
|
|
11
|
-
export interface
|
|
11
|
+
export interface LibGalleryProps {
|
|
12
12
|
|
|
13
13
|
}
|
|
14
|
-
export default function m(props:
|
|
14
|
+
export default function m(props: LibGalleryProps): any {
|
|
15
15
|
let images = LibNavigation.getArgs(props, "images", [])
|
|
16
16
|
const image = LibNavigation.getArgs(props, "image", "")
|
|
17
17
|
const index = LibNavigation.getArgs(props, "index", 0)
|
|
@@ -6,14 +6,14 @@ import React from 'react';
|
|
|
6
6
|
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
|
7
7
|
import { WebView } from 'react-native-webview';
|
|
8
8
|
|
|
9
|
-
export interface
|
|
9
|
+
export interface LibVideoArgs {
|
|
10
10
|
|
|
11
11
|
}
|
|
12
|
-
export interface
|
|
12
|
+
export interface LibVideoProps {
|
|
13
13
|
code: string,
|
|
14
14
|
style?: any
|
|
15
15
|
}
|
|
16
|
-
export default function m(props:
|
|
16
|
+
export default function m(props: LibVideoProps): any {
|
|
17
17
|
const code = props.code
|
|
18
18
|
|
|
19
19
|
if (!code) {
|
package/package.json
CHANGED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
// noPage
|
|
2
|
-
|
|
3
|
-
import { LibComponent } from "esoftplay";
|
|
4
|
-
import { Audio } from "expo-av";
|
|
5
|
-
|
|
6
|
-
export interface ContentAudioProps {
|
|
7
|
-
code: string,
|
|
8
|
-
onStatusChange: (status: any) => void
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface ContentAudioState {
|
|
12
|
-
playbackInstanceName: string,
|
|
13
|
-
muted: boolean,
|
|
14
|
-
playbackInstancePosition: any,
|
|
15
|
-
playbackInstanceDuration: any,
|
|
16
|
-
shouldPlay: boolean,
|
|
17
|
-
isPlaying: boolean,
|
|
18
|
-
isBuffering: boolean,
|
|
19
|
-
isLoading: boolean,
|
|
20
|
-
volume: number,
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// create a component
|
|
24
|
-
class eaudio extends LibComponent<ContentAudioProps, ContentAudioState> {
|
|
25
|
-
playbackInstance: any
|
|
26
|
-
state: ContentAudioState;
|
|
27
|
-
props: ContentAudioProps;
|
|
28
|
-
constructor(props: ContentAudioProps) {
|
|
29
|
-
super(props)
|
|
30
|
-
this.props = props;
|
|
31
|
-
this.playbackInstance = null;
|
|
32
|
-
this.state = {
|
|
33
|
-
playbackInstanceName: "loading...",
|
|
34
|
-
muted: false,
|
|
35
|
-
playbackInstancePosition: null,
|
|
36
|
-
playbackInstanceDuration: null,
|
|
37
|
-
shouldPlay: false,
|
|
38
|
-
isPlaying: false,
|
|
39
|
-
isBuffering: false,
|
|
40
|
-
isLoading: true,
|
|
41
|
-
volume: 1.0,
|
|
42
|
-
};
|
|
43
|
-
this._onPlaybackStatusUpdate = this._onPlaybackStatusUpdate.bind(this)
|
|
44
|
-
this._loadNewPlaybackInstance = this._loadNewPlaybackInstance.bind(this)
|
|
45
|
-
this._onPlayPausePressed = this._onPlayPausePressed.bind(this)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
componentDidMount(): void {
|
|
49
|
-
super.componentDidMount();
|
|
50
|
-
Audio.setAudioModeAsync({
|
|
51
|
-
allowsRecordingIOS: false,
|
|
52
|
-
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_DO_NOT_MIX,
|
|
53
|
-
playsInSilentModeIOS: true,
|
|
54
|
-
shouldDuckAndroid: true,
|
|
55
|
-
staysActiveInBackground: false,
|
|
56
|
-
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DUCK_OTHERS,
|
|
57
|
-
playThroughEarpieceAndroid: false
|
|
58
|
-
});
|
|
59
|
-
this._loadNewPlaybackInstance(false);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
componentWillUnmount(): void {
|
|
63
|
-
super.componentWillUnmount();
|
|
64
|
-
(async () => {
|
|
65
|
-
if (this.playbackInstance != null) {
|
|
66
|
-
await this.playbackInstance.unloadAsync();
|
|
67
|
-
this.playbackInstance.setOnPlaybackStatusUpdate(null);
|
|
68
|
-
this.playbackInstance = null;
|
|
69
|
-
}
|
|
70
|
-
})()
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async _loadNewPlaybackInstance(playing: boolean): Promise<void> {
|
|
74
|
-
if (this.playbackInstance != null) {
|
|
75
|
-
await this.playbackInstance.unloadAsync();
|
|
76
|
-
this.playbackInstance.setOnPlaybackStatusUpdate(null);
|
|
77
|
-
this.playbackInstance = null;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const source = { uri: "https://api.soundcloud.com/tracks/" + this.props.code + "/stream?client_id=4a584e57dbc1c522b0ccdb68464f6ec3" };
|
|
81
|
-
const initialStatus = {
|
|
82
|
-
shouldPlay: playing,
|
|
83
|
-
volume: this.state.volume,
|
|
84
|
-
isMuted: this.state.muted,
|
|
85
|
-
};
|
|
86
|
-
const { sound, status } = await Audio.Sound.createAsync(
|
|
87
|
-
source,
|
|
88
|
-
initialStatus,
|
|
89
|
-
this._onPlaybackStatusUpdate
|
|
90
|
-
);
|
|
91
|
-
this.playbackInstance = sound;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
_onPlaybackStatusUpdate(status: any): void {
|
|
95
|
-
if (status.isLoaded) {
|
|
96
|
-
this.setState({
|
|
97
|
-
playbackInstancePosition: status.positionMillis,
|
|
98
|
-
playbackInstanceDuration: status.durationMillis,
|
|
99
|
-
shouldPlay: status.shouldPlay,
|
|
100
|
-
isPlaying: status.isPlaying,
|
|
101
|
-
isBuffering: status.isBuffering,
|
|
102
|
-
muted: status.isMuted,
|
|
103
|
-
volume: status.volume,
|
|
104
|
-
}, () => this.props.onStatusChange(this.state.isPlaying));
|
|
105
|
-
} else {
|
|
106
|
-
if (status.error) {
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
_onPlayPausePressed(): void {
|
|
112
|
-
if (this.playbackInstance != null) {
|
|
113
|
-
if (this.state.isPlaying) {
|
|
114
|
-
this.playbackInstance.pauseAsync()
|
|
115
|
-
} else {
|
|
116
|
-
this.playbackInstance.playAsync()
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
render(): any {
|
|
122
|
-
return null
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export default eaudio;
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
|
|
3
|
-
import { ContentHeader, ContentItem, LibIcon, LibList, LibStyle, useGlobalReturn, useGlobalState } from 'esoftplay';
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import { Text, View } from 'react-native';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export interface ContentBookmarkArgs {
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface ContentBookmarkProps {
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface ContentBookmarkData {
|
|
16
|
-
id: string,
|
|
17
|
-
title: string,
|
|
18
|
-
intro: string,
|
|
19
|
-
description: string,
|
|
20
|
-
image: string,
|
|
21
|
-
created: string,
|
|
22
|
-
updated: string,
|
|
23
|
-
url: string,
|
|
24
|
-
publish: string,
|
|
25
|
-
type_id: string,
|
|
26
|
-
created_by: string,
|
|
27
|
-
created_by_alias: string,
|
|
28
|
-
modified_by: string,
|
|
29
|
-
revised: string,
|
|
30
|
-
hits: string,
|
|
31
|
-
rating: string,
|
|
32
|
-
last_hits: string,
|
|
33
|
-
is_popimage: string,
|
|
34
|
-
is_front: string,
|
|
35
|
-
is_config: string,
|
|
36
|
-
config: string,
|
|
37
|
-
}
|
|
38
|
-
export interface ContentBookmarkType {
|
|
39
|
-
ids: number[],
|
|
40
|
-
data: ContentBookmarkData[]
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const _state = useGlobalState<ContentBookmarkType>({ data: [], ids: [] }, { persistKey: 'content_bookmark_data' })
|
|
45
|
-
|
|
46
|
-
export function toggle(row: ContentBookmarkData) {
|
|
47
|
-
let { data, ids } = _state.get()
|
|
48
|
-
const idx = ids.indexOf(Number(row.id))
|
|
49
|
-
if (idx < 0) {
|
|
50
|
-
data.unshift(row)
|
|
51
|
-
ids.unshift(Number(row.id))
|
|
52
|
-
} else {
|
|
53
|
-
data.splice(idx, 1)
|
|
54
|
-
ids.splice(idx, 1)
|
|
55
|
-
}
|
|
56
|
-
_state.set({ data, ids })
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function state(): useGlobalReturn<ContentBookmarkType> {
|
|
60
|
-
return _state
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export default function m(props: ContentBookmarkProps): any {
|
|
64
|
-
const data = _state.useSelector(s => s.data)
|
|
65
|
-
return (
|
|
66
|
-
<View style={{ flex: 1 }} >
|
|
67
|
-
<ContentHeader title="Artikel tersimpan" searchButton />
|
|
68
|
-
<LibList
|
|
69
|
-
data={data}
|
|
70
|
-
ListEmptyComponent={
|
|
71
|
-
<View style={{ height: LibStyle.height - 100, justifyContent: 'center', alignItems: 'center', marginHorizontal: 24 }} >
|
|
72
|
-
<LibIcon name='bookmark-plus-outline' color={"#FD5593"} size={40} />
|
|
73
|
-
<Text style={{ fontSize: 34, marginTop: 10, fontWeight: "500", lineHeight: 40, textAlign: "center", color: "#060606" }} >Artikel belum ada</Text>
|
|
74
|
-
<Text style={{ fontSize: 16, marginTop: 10, lineHeight: 22, textAlign: "center", color: "#686868" }} >Kamu dapat menyimpan artikel untuk dibaca nanti dengan cara klik lambang bookmark</Text>
|
|
75
|
-
</View>
|
|
76
|
-
}
|
|
77
|
-
renderItem={(item) => <ContentItem {...item} />}
|
|
78
|
-
/>
|
|
79
|
-
</View>
|
|
80
|
-
)
|
|
81
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
|
|
3
|
-
import { ContentHeader, esp, LibCurl, LibList, LibNavigation, LibPicture, useGlobalReturn, useGlobalState } from 'esoftplay';
|
|
4
|
-
import React, { useEffect, useRef } from 'react';
|
|
5
|
-
import { Pressable, Text, View } from 'react-native';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export interface ContentCategoryArgs {
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface ContentCategoryProps {
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const _state = useGlobalState<any>([], { persistKey: 'content_category' })
|
|
16
|
-
|
|
17
|
-
export function state(): useGlobalReturn<any> {
|
|
18
|
-
return _state
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export default function m(props: ContentCategoryProps): any {
|
|
23
|
-
let { url } = useRef<any>(LibNavigation.getArgsAll(props)).current
|
|
24
|
-
const conf = esp.config()
|
|
25
|
-
url = url || conf.content
|
|
26
|
-
const data = _state.useSelector(s => s)
|
|
27
|
-
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
new LibCurl(url + 'menu', null,
|
|
30
|
-
(res, msg) => {
|
|
31
|
-
_state.set(res)
|
|
32
|
-
},
|
|
33
|
-
(msg) => {
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
}, [])
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<View style={{ flex: 1 }} >
|
|
41
|
-
<ContentHeader title="Kategori" searchButton />
|
|
42
|
-
<LibList
|
|
43
|
-
style={{ flex: 1, padding: 5 }}
|
|
44
|
-
data={data?.list?.[0]?.filter?.((row: any) => row.par_id == 0)}
|
|
45
|
-
numColumns={3}
|
|
46
|
-
renderItem={(item) => {
|
|
47
|
-
return (
|
|
48
|
-
<Pressable
|
|
49
|
-
onPress={() => { LibNavigation.push('content/list', { url: item.url, title: item.title, id: item.id }) }}
|
|
50
|
-
style={{ borderRadius: 8, backgroundColor: "#f2f2f2", flex: 0.35, margin: 5, alignItems: 'center' }} >
|
|
51
|
-
<LibPicture source={{ uri: item.image }} style={{ height: 70, width: 70, marginTop: 16, }} />
|
|
52
|
-
<Text style={{ fontSize: 12, fontWeight: "500", lineHeight: 20, color: "#060606", marginBottom: 12, }}>{item?.title}</Text>
|
|
53
|
-
</Pressable>
|
|
54
|
-
)
|
|
55
|
-
}}
|
|
56
|
-
/>
|
|
57
|
-
</View>
|
|
58
|
-
)
|
|
59
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
// noPage
|
|
3
|
-
import { ContentCategoryProperty, esp, LibCurl, LibNavigation, LibPicture } from 'esoftplay';
|
|
4
|
-
import React, { useEffect, useRef } from 'react';
|
|
5
|
-
import { Pressable, ScrollView, Text, View } from 'react-native';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export interface ContentCategory_listArgs {
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface ContentCategory_listProps {
|
|
12
|
-
id: number
|
|
13
|
-
}
|
|
14
|
-
export default function m(props: ContentCategory_listProps): any {
|
|
15
|
-
const { id } = props
|
|
16
|
-
let { url } = useRef<any>(LibNavigation.getArgsAll(props)).current
|
|
17
|
-
const conf = esp.config()
|
|
18
|
-
url = url || conf.content
|
|
19
|
-
const menu = ContentCategoryProperty.state().useSelector(s => s)
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
new LibCurl(url + 'menu', null,
|
|
23
|
-
(res, msg) => {
|
|
24
|
-
ContentCategoryProperty.state().set(res)
|
|
25
|
-
},
|
|
26
|
-
(msg) => {
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
)
|
|
30
|
-
}, [])
|
|
31
|
-
|
|
32
|
-
if (id == 0)
|
|
33
|
-
return null
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<View style={{}} >
|
|
37
|
-
<ScrollView horizontal nestedScrollEnabled
|
|
38
|
-
style={{ margin: 0 }} >
|
|
39
|
-
{
|
|
40
|
-
menu?.list?.[0]?.filter?.((row: any) => row.par_id == id).map((row: any) => (
|
|
41
|
-
<Pressable
|
|
42
|
-
onPress={() => { LibNavigation.push('content/list', { url: row.url, title: row.title, id: row.id }) }}
|
|
43
|
-
style={{ borderRadius: 8, flexDirection: 'row', borderWidth: 1, borderColor: "#f2f2f2", margin: 5, padding: 8, alignItems: 'center' }} >
|
|
44
|
-
<LibPicture source={{ uri: row.image }} style={{ width: 20, height: 20, resizeMode: 'contain' }} />
|
|
45
|
-
<Text style={{ marginLeft: 8 }} >{row.title}</Text>
|
|
46
|
-
</Pressable>
|
|
47
|
-
))
|
|
48
|
-
}
|
|
49
|
-
</ScrollView>
|
|
50
|
-
</View>
|
|
51
|
-
)
|
|
52
|
-
}
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
|
|
3
|
-
import { ContentComment_item, ContentHeader, LibCurl, LibIcon, LibInfinite, LibInput, LibKeyboard_avoid, LibNavigation, LibObject, LibSociallogin, LibStyle, LibToastProperty, LibUtils, useGlobalReturn, useGlobalState, useSafeState } from 'esoftplay';
|
|
4
|
-
import esp from 'esoftplay/esp';
|
|
5
|
-
import React, { useEffect, useRef } from 'react';
|
|
6
|
-
import { Alert, Image, Pressable, Text, View } from 'react-native';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export interface ContentCommentArgs {
|
|
10
|
-
id: number | string
|
|
11
|
-
}
|
|
12
|
-
export interface ContentCommentProps {
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
const _state = useGlobalState<any>(undefined, {
|
|
16
|
-
persistKey: 'content_comment_user',
|
|
17
|
-
listener: (data) => {
|
|
18
|
-
LibSociallogin.setUser(data)
|
|
19
|
-
}
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
export function state(): useGlobalReturn<any> {
|
|
23
|
-
return _state
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default function m(props: ContentCommentProps): any {
|
|
27
|
-
const listComment = useRef<LibInfinite>(null)
|
|
28
|
-
const commentInput = useRef<LibInput>(null)
|
|
29
|
-
let { url, url_post, id, par_id, header } = LibNavigation.getArgsAll(props)
|
|
30
|
-
|
|
31
|
-
url = useRef(url || esp.config('content') + 'user/commentlist/' + id).current
|
|
32
|
-
url_post = useRef(url_post || esp.config('content') + 'user/commentpost/' + id).current
|
|
33
|
-
let comment = useRef('').current
|
|
34
|
-
const config = esp.config()
|
|
35
|
-
const comment_login = esp.config("comment_login");
|
|
36
|
-
const [headerComment, setHeaderComment] = useSafeState(header)
|
|
37
|
-
const [showLoginForm, setShowLoginForm] = useSafeState(false)
|
|
38
|
-
const [refresher, setRefresher] = useSafeState(1)
|
|
39
|
-
|
|
40
|
-
if (par_id) {
|
|
41
|
-
url += url.includes('?') ? '&par_id=' + par_id : '?par_id=' + par_id
|
|
42
|
-
url_post += url_post.includes('?') ? '&par_id=' + par_id : '?par_id=' + par_id
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const [user, setUser] = _state.useState()
|
|
46
|
-
|
|
47
|
-
function refresh() {
|
|
48
|
-
if (header) {
|
|
49
|
-
setHeaderComment(LibObject.update(headerComment, (count) => count + 1)('reply'))
|
|
50
|
-
}
|
|
51
|
-
setRefresher(refresher + 1)
|
|
52
|
-
commentInput.current?.setText('')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
LibSociallogin.getUser(setUser)
|
|
57
|
-
}, [])
|
|
58
|
-
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
if (showLoginForm && user) {
|
|
61
|
-
setShowLoginForm(false)
|
|
62
|
-
}
|
|
63
|
-
}, [user])
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
function send() {
|
|
67
|
-
if (user) {
|
|
68
|
-
if (comment != '') {
|
|
69
|
-
const post = { ...user, content: comment }
|
|
70
|
-
new LibCurl(url_post, post,
|
|
71
|
-
(res, msg) => {
|
|
72
|
-
refresh()
|
|
73
|
-
},
|
|
74
|
-
(msg) => {
|
|
75
|
-
const success = msg.includes('<div class="alert alert-success" role="alert">')
|
|
76
|
-
if (!success) {
|
|
77
|
-
let _msg = (/<\/span>(.*)<\/div>/g).exec(msg)
|
|
78
|
-
Alert.alert('Komentar gagal dikirim', _msg?.[1])
|
|
79
|
-
} else {
|
|
80
|
-
refresh()
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
)
|
|
84
|
-
} else {
|
|
85
|
-
LibToastProperty.show('Cek koment')
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
if (comment_login == 1 && !user) {
|
|
89
|
-
setShowLoginForm(true)
|
|
90
|
-
LibToastProperty.show('Silahkan login terlebih dahulu')
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (showLoginForm) {
|
|
97
|
-
return (
|
|
98
|
-
<View style={{ flex: 1, backgroundColor: "white" }} >
|
|
99
|
-
<ContentHeader title="Login dengan akun" />
|
|
100
|
-
<View style={{ flexDirection: "row", alignItems: "center", justifyContent: "center", paddingRight: 16 }} >
|
|
101
|
-
<Text style={{ flex: 1, padding: 10, color: '#606060' }} >{"Silakan login dengan salah satu akun sosial media berikut untuk dapat mengirimkan komentar"}</Text>
|
|
102
|
-
<View style={{ justifyContent: "center" }} >
|
|
103
|
-
<Pressable
|
|
104
|
-
onPress={() => { setShowLoginForm(false) }} >
|
|
105
|
-
<Text style={{ color: LibStyle.colorPrimary }} >{"BATAL"}</Text>
|
|
106
|
-
</Pressable>
|
|
107
|
-
</View>
|
|
108
|
-
</View>
|
|
109
|
-
<LibSociallogin
|
|
110
|
-
url={config.content + "user/commentlogin"}
|
|
111
|
-
onResult={setUser}
|
|
112
|
-
/>
|
|
113
|
-
</View>
|
|
114
|
-
)
|
|
115
|
-
}
|
|
116
|
-
let x = (item) => <ContentComment_item url={url} url_post={url_post} {...item} />
|
|
117
|
-
|
|
118
|
-
return (
|
|
119
|
-
<View style={{ flex: 1 }} >
|
|
120
|
-
<ContentHeader backButton title="Komentar" />
|
|
121
|
-
<LibKeyboard_avoid
|
|
122
|
-
key={refresher + ''}
|
|
123
|
-
style={{ flex: 1, backgroundColor: '#f9f9f9' }} >
|
|
124
|
-
<LibInfinite
|
|
125
|
-
ref={listComment}
|
|
126
|
-
url={url}
|
|
127
|
-
ListHeaderComponent={
|
|
128
|
-
header &&
|
|
129
|
-
<View style={{ flexDirection: 'row', backgroundColor: 'white', borderLeftWidth: headerComment.par_id > 0 ? 60 : 0, borderLeftColor: '#f9f9f9', borderBottomWidth: 8, borderBottomColor: '#f9f9f9' }} >
|
|
130
|
-
<View style={{ marginTop: 18, marginLeft: 16 }} >
|
|
131
|
-
<Image source={{ uri: headerComment.image }} style={{ height: 50, backgroundColor: '#f8f8f8', width: 50, resizeMode: 'cover', overflow: 'hidden', borderRadius: 25 }} />
|
|
132
|
-
</View>
|
|
133
|
-
<View style={{ flex: 1, paddingVertical: 16, marginHorizontal: 16 }} >
|
|
134
|
-
<Text style={{ fontSize: 10, fontWeight: "500", letterSpacing: 1.5, color: "#686868" }} >{LibUtils.moment(headerComment.date).format('DD MMM YYYY HH:mm').toUpperCase()}</Text>
|
|
135
|
-
<Text style={{ fontSize: 16, fontWeight: "500", lineHeight: 20, color: "#060606", marginTop: 8 }} >{headerComment.name}</Text>
|
|
136
|
-
<Text style={{ fontSize: 14, fontWeight: "500", lineHeight: 20, color: "#606060" }} >{headerComment.content}</Text>
|
|
137
|
-
<Pressable style={{ flexDirection: 'row' }} >
|
|
138
|
-
<View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 9, /* backgroundColor: '#f1f1f1', padding: 3, borderRadius: 6 */ }} >
|
|
139
|
-
<LibIcon.AntDesign name='message1' size={12} color="#ababab" />
|
|
140
|
-
<Text style={{ fontSize: 12, lineHeight: 16, color: "#ababab", marginLeft: 5 }} >{headerComment.reply} Balasan</Text>
|
|
141
|
-
</View>
|
|
142
|
-
</Pressable>
|
|
143
|
-
</View>
|
|
144
|
-
</View>
|
|
145
|
-
}
|
|
146
|
-
renderItem={x}
|
|
147
|
-
/>
|
|
148
|
-
<View style={{ flexDirection: 'row', backgroundColor: 'white', alignItems: 'center' }} >
|
|
149
|
-
{
|
|
150
|
-
(comment_login == 1) &&
|
|
151
|
-
<Pressable onPress={() => setShowLoginForm(true)} >
|
|
152
|
-
<Image source={{ uri: user?.image }} style={{ height: 40, width: 40, borderRadius: 20, backgroundColor: '#f2f2f2', marginLeft: 16 }} />
|
|
153
|
-
</Pressable>
|
|
154
|
-
}
|
|
155
|
-
<LibInput base
|
|
156
|
-
ref={commentInput}
|
|
157
|
-
placeholder={"Kirim Komentar"}
|
|
158
|
-
onChangeText={(text) => comment = text}
|
|
159
|
-
style={{ flex: 1, minHeight: 40, paddingHorizontal: 8, borderRadius: 8, backgroundColor: '#f9f9f9', marginVertical: 5, marginHorizontal: 16 }}
|
|
160
|
-
/>
|
|
161
|
-
{
|
|
162
|
-
(!(comment_login == 1 && !user)) &&
|
|
163
|
-
<Pressable
|
|
164
|
-
onPress={() => send()}
|
|
165
|
-
style={{ minHeight: 40, width: 40, marginRight: 16, backgroundColor: LibStyle.colorPrimary, justifyContent: 'center', alignItems: 'center', borderRadius: 20 }} >
|
|
166
|
-
<LibIcon.Ionicons name='md-send' color={LibStyle.colorAccent} />
|
|
167
|
-
</Pressable>
|
|
168
|
-
}
|
|
169
|
-
</View>
|
|
170
|
-
</LibKeyboard_avoid>
|
|
171
|
-
</View>
|
|
172
|
-
)
|
|
173
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
// noPage
|
|
3
|
-
|
|
4
|
-
import { LibIcon, LibNavigation, LibUtils } from 'esoftplay';
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import { Image, Pressable, Text, View } from 'react-native';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export interface ContentComment_itemArgs {
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
export interface ContentComment_itemProps {
|
|
13
|
-
id: number,
|
|
14
|
-
url: string,
|
|
15
|
-
url_post: string,
|
|
16
|
-
par_id: number,
|
|
17
|
-
name: string,
|
|
18
|
-
image: string,
|
|
19
|
-
content: string,
|
|
20
|
-
email: string,
|
|
21
|
-
website: string,
|
|
22
|
-
date: string,
|
|
23
|
-
reply: number
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default function m(props: ContentComment_itemProps): any {
|
|
27
|
-
const styleId_Z2wK9pa: any = { flexDirection: 'row', backgroundColor: 'white', borderLeftWidth: props.par_id > 0 ? 50 : 0, borderLeftColor: '#f9f9f9' }
|
|
28
|
-
return (
|
|
29
|
-
<View style={styleId_Z2wK9pa} >
|
|
30
|
-
<View style={styleId_14E1yO} >
|
|
31
|
-
<Image source={{ uri: props.image }} style={styleId_2e0Fad} />
|
|
32
|
-
</View>
|
|
33
|
-
<View style={styleId_ZLhjsk} >
|
|
34
|
-
<Text style={styleId_ZCtIoL} >{LibUtils.moment(props.date).format('DD MMM YYYY HH:mm').toUpperCase()}</Text>
|
|
35
|
-
<Text style={styleId_ZmiARo} >{props.name}</Text>
|
|
36
|
-
<Text style={styleId_1jN6UB} >{props.content}</Text>
|
|
37
|
-
<Pressable
|
|
38
|
-
onPress={() => LibNavigation.push('content/comment', {
|
|
39
|
-
header: { ...props, par_id: 0 },
|
|
40
|
-
url: props.url, url_post: props.url_post, par_id: props.id
|
|
41
|
-
})}
|
|
42
|
-
style={styleId_Z1IS0fI} >
|
|
43
|
-
<View style={styleId_Z2nP5oE} >
|
|
44
|
-
<LibIcon.AntDesign name='message1' size={12} color="#ababab" />
|
|
45
|
-
<Text style={styleId_Z1pDQI5} >{props.reply} Balasan</Text>
|
|
46
|
-
</View>
|
|
47
|
-
</Pressable>
|
|
48
|
-
</View>
|
|
49
|
-
</View>
|
|
50
|
-
)
|
|
51
|
-
}
|
|
52
|
-
const styleId_14E1yO: any = { marginTop: 18, marginLeft: 16 }
|
|
53
|
-
const styleId_2e0Fad: any = { height: 50, width: 50, backgroundColor: '#f8f8f8', resizeMode: 'cover', overflow: 'hidden', borderRadius: 25 }
|
|
54
|
-
const styleId_ZLhjsk: any = { flex: 1, paddingVertical: 16, marginHorizontal: 16, borderBottomWidth: 1, borderBottomColor: '#f9f9f9' }
|
|
55
|
-
const styleId_ZCtIoL: any = { fontSize: 10, fontWeight: "500", letterSpacing: 1.5, color: "#686868" }
|
|
56
|
-
const styleId_ZmiARo: any = { fontSize: 16, fontWeight: "500", lineHeight: 20, color: "#060606", marginTop: 8 }
|
|
57
|
-
const styleId_1jN6UB: any = { fontSize: 14, fontWeight: "500", lineHeight: 20, color: "#606060" }
|
|
58
|
-
const styleId_Z1IS0fI: any = { flexDirection: 'row' }
|
|
59
|
-
const styleId_Z2nP5oE: any = { flexDirection: 'row', alignItems: 'center', marginTop: 9, backgroundColor: '#f1f1f1', padding: 3, borderRadius: 6 }
|
|
60
|
-
const styleId_Z1pDQI5: any = { fontSize: 12, lineHeight: 16, color: "#ababab", marginLeft: 5 }
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// noPage
|
|
2
|
-
|
|
3
|
-
import { LibComponent, useGlobalReturn, useGlobalState } from 'esoftplay';
|
|
4
|
-
export interface ContentConfigProps {
|
|
5
|
-
navigation: any
|
|
6
|
-
}
|
|
7
|
-
export interface ContentConfigState {
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const state = useGlobalState({
|
|
13
|
-
list: {
|
|
14
|
-
template: "list.html.php",
|
|
15
|
-
title: "1",
|
|
16
|
-
title_link: "1",
|
|
17
|
-
intro: "1",
|
|
18
|
-
created: "1",
|
|
19
|
-
modified: "1",
|
|
20
|
-
author: "0",
|
|
21
|
-
tag: "1",
|
|
22
|
-
tag_link: "1",
|
|
23
|
-
rating: "1",
|
|
24
|
-
read_more: "1",
|
|
25
|
-
tot_list: "12",
|
|
26
|
-
thumbnail: "1"
|
|
27
|
-
},
|
|
28
|
-
detail: {
|
|
29
|
-
template: "detail.html.php",
|
|
30
|
-
title: "1",
|
|
31
|
-
created: "1",
|
|
32
|
-
modified: 0,
|
|
33
|
-
author: "1",
|
|
34
|
-
tag: "1",
|
|
35
|
-
tag_link: "1",
|
|
36
|
-
rating: "1",
|
|
37
|
-
rating_vote: "1",
|
|
38
|
-
thumbsize: "250",
|
|
39
|
-
comment: 1,
|
|
40
|
-
comment_auto: "1",
|
|
41
|
-
comment_list: "9",
|
|
42
|
-
comment_form: "1",
|
|
43
|
-
comment_emoticons: "1",
|
|
44
|
-
comment_spam: "0",
|
|
45
|
-
comment_email: "1",
|
|
46
|
-
pdf: "1",
|
|
47
|
-
print: "1",
|
|
48
|
-
email: "1",
|
|
49
|
-
share: "1"
|
|
50
|
-
}
|
|
51
|
-
}, { persistKey: 'content_config' })
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class m extends LibComponent<ContentConfigProps, ContentConfigState> {
|
|
55
|
-
|
|
56
|
-
static state(): useGlobalReturn<any> {
|
|
57
|
-
return state
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
static setList(config: any): void {
|
|
61
|
-
state.set({
|
|
62
|
-
...state.get(),
|
|
63
|
-
list: config
|
|
64
|
-
})
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static setDetail(config: any): void {
|
|
68
|
-
state.set({
|
|
69
|
-
...state.get(),
|
|
70
|
-
detail: config
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
render(): any {
|
|
75
|
-
return null
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export default m;
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
|
|
3
|
-
import { applyStyle, ContentAudio, ContentConfig, ContentItem, ContentVideo, LibCurl, LibIcon, LibNavigation, LibObject, LibScroll, LibStyle, LibUtils, LibWebview, useSafeState } from 'esoftplay';
|
|
4
|
-
import { LinearGradient } from 'expo-linear-gradient';
|
|
5
|
-
import React, { useEffect, useRef } from 'react';
|
|
6
|
-
import { ImageBackground, Linking, Pressable, Text, View } from 'react-native';
|
|
7
|
-
|
|
8
|
-
export interface ContentDetailArgs {
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface ContentDetailProps {
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
export default function m(props: ContentDetailProps): any {
|
|
15
|
-
const { id, url, title, image, created } = LibNavigation.getArgsAll(props)
|
|
16
|
-
const [result, setResult] = useSafeState<any>({ id, url, title, image, created })
|
|
17
|
-
const [isAudioPlaying, setIsAudioPlaying] = useSafeState(false)
|
|
18
|
-
const audioRef = useRef<ContentAudio>(null)
|
|
19
|
-
const configlist = ContentConfig.state().get().detail
|
|
20
|
-
function loadData() {
|
|
21
|
-
new LibCurl(url, null,
|
|
22
|
-
(res, msg) => {
|
|
23
|
-
setResult(res)
|
|
24
|
-
ContentConfig.state().set(LibObject.set(ContentConfig.state().get(), res.config)('detail'))
|
|
25
|
-
},
|
|
26
|
-
(msg) => {
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
loadData()
|
|
34
|
-
return () => audioRef.current?.componentWillUnmount()
|
|
35
|
-
}, [])
|
|
36
|
-
|
|
37
|
-
const isDownload = result.link != "" && result.type === "download"
|
|
38
|
-
const isAudio = result.code != "" && result.type === "audio"
|
|
39
|
-
const isVideo = result.code != "" && result.type === "video"
|
|
40
|
-
const _images = result?.images?.length > 0 ? result.images : [{ image: result.image }]
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<>
|
|
44
|
-
<LibScroll
|
|
45
|
-
stickyHeaderIndices={isVideo ? [0] : undefined}
|
|
46
|
-
onRefresh={loadData} style={{ flex: 1 }} >
|
|
47
|
-
{
|
|
48
|
-
isVideo ?
|
|
49
|
-
<>
|
|
50
|
-
<View style={{ backgroundColor: 'black', paddingTop: LibStyle.STATUSBAR_HEIGHT }} >
|
|
51
|
-
<ContentVideo code={result.code} />
|
|
52
|
-
</View>
|
|
53
|
-
</>
|
|
54
|
-
:
|
|
55
|
-
<Pressable onPress={() => LibNavigation.navigate('content/gallery', { images: _images })} >
|
|
56
|
-
<ImageBackground
|
|
57
|
-
source={{ uri: image }}
|
|
58
|
-
style={{ height: LibStyle.height * 0.718, marginBottom: 4, ...LibStyle.elevation(4), width: LibStyle.width, justifyContent: 'flex-end' }}>
|
|
59
|
-
<LinearGradient colors={['transparent', 'rgba(0,0,0,0.8)']} style={applyStyle({ padding: 16, paddingTop: 90 })} >
|
|
60
|
-
{result?.images?.length > 0 && <LibIcon.Ionicons name="copy-outline" color={'white'} size={30} style={{ transform: [{ scaleX: -1 }] }} />}
|
|
61
|
-
{
|
|
62
|
-
configlist.created == 1 &&
|
|
63
|
-
<Text style={applyStyle({ fontSize: 10, fontWeight: "500", letterSpacing: 1.5, color: "white", textTransform: 'uppercase', marginTop: 12 })} >{LibUtils.moment(result.created, 'id').format('DD MMM YYYY HH:mm')}</Text>
|
|
64
|
-
}
|
|
65
|
-
{
|
|
66
|
-
configlist.title == 1 &&
|
|
67
|
-
<Text style={applyStyle({ fontSize: 34, fontWeight: "500", lineHeight: 40, color: "white", marginTop: 5 })} >{result.title}</Text>
|
|
68
|
-
}
|
|
69
|
-
{
|
|
70
|
-
configlist.author == 1 &&
|
|
71
|
-
<View style={applyStyle({ flexDirection: 'row', marginTop: 5 })} >
|
|
72
|
-
<View style={applyStyle({ backgroundColor: 'rgba(255,255,255,0.6)', borderRadius: 4, paddingHorizontal: 10, })} >
|
|
73
|
-
<Text style={applyStyle({ fontSize: 14, lineHeight: 20, color: LibStyle.colorPrimary, })} >{result.created_by_alias}</Text>
|
|
74
|
-
</View>
|
|
75
|
-
</View>
|
|
76
|
-
}
|
|
77
|
-
</LinearGradient>
|
|
78
|
-
</ImageBackground>
|
|
79
|
-
</Pressable>
|
|
80
|
-
}
|
|
81
|
-
{
|
|
82
|
-
isAudio &&
|
|
83
|
-
<>
|
|
84
|
-
<ContentAudio code={result.code} onStatusChange={setIsAudioPlaying} ref={audioRef} />
|
|
85
|
-
<Pressable onPress={() => audioRef.current?._onPlayPausePressed()} style={{ backgroundColor: '#f8f8f8', borderWidth: 1, borderColor: LibStyle.colorPrimary, borderRadius: 13, padding: 16, margin: 16, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }} >
|
|
86
|
-
<LibIcon.AntDesign name={isAudioPlaying ? 'pause' : 'play'} color={LibStyle.colorPrimary} />
|
|
87
|
-
<Text style={{ fontSize: 16, marginLeft: 16, fontWeight: "500", letterSpacing: 1.2, color: LibStyle.colorPrimary }} >Klik disini untuk memainkan audio</Text>
|
|
88
|
-
</Pressable>
|
|
89
|
-
</>
|
|
90
|
-
}
|
|
91
|
-
{
|
|
92
|
-
isDownload &&
|
|
93
|
-
<Pressable onPress={() => Linking.openURL(result.link)} style={{ backgroundColor: '#f8f8f8', borderWidth: 1, borderColor: LibStyle.colorPrimary, borderRadius: 13, padding: 16, margin: 16, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }} >
|
|
94
|
-
<LibIcon.SimpleLineIcons name='cloud-download' color={LibStyle.colorPrimary} />
|
|
95
|
-
<Text style={{ fontSize: 16, marginLeft: 16, fontWeight: "500", letterSpacing: 1.2, color: LibStyle.colorPrimary }} >Klik disini untuk mengunduh</Text>
|
|
96
|
-
</Pressable>
|
|
97
|
-
}
|
|
98
|
-
{
|
|
99
|
-
isVideo &&
|
|
100
|
-
<View pointerEvents={'none'} style={applyStyle({ padding: 17, paddingVertical: 5 })} >
|
|
101
|
-
{
|
|
102
|
-
configlist.created == 1 &&
|
|
103
|
-
<Text style={applyStyle({ fontSize: 10, fontWeight: "500", letterSpacing: 1.5, color: "#555", textTransform: 'uppercase', marginTop: 12 })} >{LibUtils.moment(result.created, 'id').format('DD MMM YYYY HH:mm')}</Text>
|
|
104
|
-
}
|
|
105
|
-
{
|
|
106
|
-
configlist.title == 1 &&
|
|
107
|
-
<Text style={applyStyle({ fontSize: 34, fontWeight: "500", lineHeight: 40, color: "#555", marginTop: 5 })} >{result.title}</Text>
|
|
108
|
-
}
|
|
109
|
-
{
|
|
110
|
-
configlist.author == 1 &&
|
|
111
|
-
<View style={applyStyle({ flexDirection: 'row', marginTop: 5 })} >
|
|
112
|
-
<Text style={applyStyle({ fontSize: 14, lineHeight: 20, color: LibStyle.colorPrimary, })} >{result.created_by_alias}</Text>
|
|
113
|
-
</View>
|
|
114
|
-
}
|
|
115
|
-
</View>
|
|
116
|
-
}
|
|
117
|
-
<LibWebview
|
|
118
|
-
source={{ html: result.content }}
|
|
119
|
-
style={{ flex: 1, marginVertical: 20 }}
|
|
120
|
-
onFinishLoad={() => { }}
|
|
121
|
-
/>
|
|
122
|
-
{
|
|
123
|
-
configlist.comment == 1 &&
|
|
124
|
-
<View style={{ alignItems: 'center', borderBottomWidth: 8, borderBottomColor: '#f2f2f2', paddingBottom: 13 }} >
|
|
125
|
-
<Pressable onPress={() => LibNavigation.navigate('content/comment', { id: result.id })} style={{ borderRadius: 8, paddingHorizontal: 24, paddingVertical: 10, backgroundColor: LibStyle.colorPrimary, }} >
|
|
126
|
-
<Text style={{ fontSize: 14, fontWeight: "500", lineHeight: 18, color: LibStyle.colorAccent }} >KOMENTAR</Text>
|
|
127
|
-
</Pressable>
|
|
128
|
-
</View>
|
|
129
|
-
}
|
|
130
|
-
{result?.related?.length > 0 && <Text style={{ fontSize: 20, fontWeight: "500", lineHeight: 26, color: "#060606", marginLeft: 16, marginBottom: 13, marginTop: 20 }} >Artikel Terkait</Text>}
|
|
131
|
-
{
|
|
132
|
-
result?.related?.map?.((rel: any, i: number) => {
|
|
133
|
-
return (<ContentItem key={rel + i} {...rel} />)
|
|
134
|
-
})
|
|
135
|
-
}
|
|
136
|
-
</LibScroll>
|
|
137
|
-
<View style={{ position: 'absolute', top: 0, left: 0, right: 0, flexDirection: 'row', justifyContent: 'space-between', paddingTop: LibStyle.STATUSBAR_HEIGHT_MASTER + 14, paddingHorizontal: 16 }} >
|
|
138
|
-
<Pressable onPress={() => LibNavigation.back()} style={{ height: 40, width: 40, borderRadius: 20, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(0,0,0,0.2)' }} >
|
|
139
|
-
<LibIcon name='arrow-left' color='white' />
|
|
140
|
-
</Pressable>
|
|
141
|
-
{
|
|
142
|
-
configlist.share == 1 &&
|
|
143
|
-
<Pressable onPress={() => LibUtils.share(url.replace('://data.', '://'))} style={{ height: 40, width: 40, borderRadius: 20, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(0,0,0,0.2)' }} >
|
|
144
|
-
<LibIcon name="share" color={'white'} />
|
|
145
|
-
</Pressable>
|
|
146
|
-
}
|
|
147
|
-
</View>
|
|
148
|
-
</>
|
|
149
|
-
)
|
|
150
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
// noPage
|
|
3
|
-
|
|
4
|
-
import { LibIcon, LibNavigation, LibStatusbar, LibStyle } from 'esoftplay';
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import { Pressable, Text, View } from 'react-native';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export interface ContentHeaderArgs {
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
export interface ContentHeaderProps {
|
|
13
|
-
title: string,
|
|
14
|
-
backButton?: boolean
|
|
15
|
-
searchButton?: boolean
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default function m(props: ContentHeaderProps): any {
|
|
19
|
-
return (
|
|
20
|
-
<>
|
|
21
|
-
<LibStatusbar style='light' />
|
|
22
|
-
<View style={{ flexDirection: 'row', alignItems: 'center', paddingBottom: 12, paddingTop: LibStyle.STATUSBAR_HEIGHT_MASTER + 14, paddingHorizontal: 16, backgroundColor: LibStyle.colorPrimary }} >
|
|
23
|
-
{
|
|
24
|
-
props.backButton &&
|
|
25
|
-
<Pressable
|
|
26
|
-
onPress={() => LibNavigation.back()}
|
|
27
|
-
style={{ paddingRight: 16 }}>
|
|
28
|
-
<LibIcon name='arrow-left' color={LibStyle.colorAccent} />
|
|
29
|
-
</Pressable>
|
|
30
|
-
}
|
|
31
|
-
<View style={{ flex: 1 }} >
|
|
32
|
-
<Text style={{ fontSize: 20, fontWeight: "500", lineHeight: 26, color: LibStyle.colorAccent }} >{props?.title}</Text>
|
|
33
|
-
{/* {
|
|
34
|
-
!props.backButton &&
|
|
35
|
-
<Text style={{ fontSize: 14, lineHeight: 20, color: LibStyle.colorAccent }} >{LibUtils.moment(undefined, 'id').format('dddd, DD MMMM YYYY')}</Text>
|
|
36
|
-
} */}
|
|
37
|
-
</View>
|
|
38
|
-
{
|
|
39
|
-
props.searchButton &&
|
|
40
|
-
<Pressable
|
|
41
|
-
onPress={() => LibNavigation.navigate('content/search')}
|
|
42
|
-
style={{ paddingLeft: 16 }}>
|
|
43
|
-
<LibIcon name='magnify' color={LibStyle.colorAccent} />
|
|
44
|
-
</Pressable>
|
|
45
|
-
}
|
|
46
|
-
</View>
|
|
47
|
-
</>
|
|
48
|
-
)
|
|
49
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
|
|
3
|
-
import { ContentBookmark, ContentCategory, ContentList, LibIcon, LibStyle, useGlobalReturn, useGlobalState } from 'esoftplay';
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import { Pressable, Text, View } from 'react-native';
|
|
6
|
-
|
|
7
|
-
export interface ContentIndexArgs {
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
export interface ContentIndexProps {
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
const _state = useGlobalState(0)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export function state(): useGlobalReturn<number> {
|
|
17
|
-
return _state
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default function m(props: ContentIndexProps): any {
|
|
21
|
-
const [idx, setIdx] = _state.useState()
|
|
22
|
-
const Aview = [ContentList, ContentCategory, ContentBookmark][idx]
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<>
|
|
26
|
-
<Aview />
|
|
27
|
-
<View style={styleId_ZKPd2h} >
|
|
28
|
-
<Pressable onPress={() => setIdx(0)} style={styleId_Z2pKvdh} >
|
|
29
|
-
<>
|
|
30
|
-
<LibIcon name='home' size={26} color={idx == 0 ? LibStyle.colorPrimary : 'grey'} />
|
|
31
|
-
<Text style={{ ...styleId_Z25Lwf9, color: idx == 0 ? LibStyle.colorPrimary : 'grey' }} >Beranda</Text>
|
|
32
|
-
</>
|
|
33
|
-
</Pressable>
|
|
34
|
-
<Pressable onPress={() => setIdx(1)} style={styleId_Z2pKvdh} >
|
|
35
|
-
<>
|
|
36
|
-
<LibIcon name='view-dashboard' size={26} color={idx == 1 ? LibStyle.colorPrimary : 'grey'} />
|
|
37
|
-
<Text style={{ ...styleId_Z25Lwf9, color: idx == 1 ? LibStyle.colorPrimary : 'grey' }} >Kategori</Text>
|
|
38
|
-
</>
|
|
39
|
-
</Pressable>
|
|
40
|
-
<Pressable onPress={() => setIdx(2)} style={styleId_Z2pKvdh} >
|
|
41
|
-
<>
|
|
42
|
-
<LibIcon name='bookmark' size={26} color={idx == 2 ? LibStyle.colorPrimary : 'grey'} />
|
|
43
|
-
<Text style={{ ...styleId_Z25Lwf9, color: idx == 2 ? LibStyle.colorPrimary : 'grey' }} >Disimpan</Text>
|
|
44
|
-
</>
|
|
45
|
-
</Pressable>
|
|
46
|
-
</View>
|
|
47
|
-
</>
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
const styleId_ZKPd2h: any = { height: 56, flexDirection: 'row', borderTopWidth: 3, borderTopColor: '#f8f8f8' }
|
|
51
|
-
const styleId_Z2pKvdh: any = { flex: 1, justifyContent: 'center', alignItems: 'center' }
|
|
52
|
-
const styleId_Z25Lwf9: any = { fontSize: 12, fontWeight: "500", lineHeight: 16, textAlign: "center", color: 'grey' }
|
package/modules/content/item.tsx
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
// noPage
|
|
3
|
-
|
|
4
|
-
import { ContentBookmarkProperty, ContentConfig, LibIcon, LibNavigation, LibPicture, LibStyle, LibUtils } from 'esoftplay';
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import { Image, Linking, Pressable, Text, View } from 'react-native';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export interface ContentItemArgs {
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
export interface ContentItemProps {
|
|
13
|
-
id: string,
|
|
14
|
-
title: string,
|
|
15
|
-
intro: string,
|
|
16
|
-
description: string,
|
|
17
|
-
image: string,
|
|
18
|
-
created: string,
|
|
19
|
-
updated: string,
|
|
20
|
-
url: string,
|
|
21
|
-
publish: string,
|
|
22
|
-
type_id: string,
|
|
23
|
-
created_by: string,
|
|
24
|
-
created_by_alias: string,
|
|
25
|
-
modified_by: string,
|
|
26
|
-
revised: string,
|
|
27
|
-
hits: string,
|
|
28
|
-
rating: string,
|
|
29
|
-
last_hits: string,
|
|
30
|
-
is_popimage: string,
|
|
31
|
-
is_front: string,
|
|
32
|
-
is_config: string,
|
|
33
|
-
config: string,
|
|
34
|
-
}
|
|
35
|
-
export default function m(props: ContentItemProps): any {
|
|
36
|
-
const isBook = ContentBookmarkProperty.state().useSelector(s => s.ids.includes(Number(props.id)))
|
|
37
|
-
const configlist = ContentConfig.state().get().list
|
|
38
|
-
if (props.created == 'sponsor')
|
|
39
|
-
if (props.title == '')
|
|
40
|
-
return (
|
|
41
|
-
<Pressable onPress={() => Linking.openURL(props.url)} >
|
|
42
|
-
<Image source={{ uri: props.image }} style={styleId_Z1pdPtF} />
|
|
43
|
-
</Pressable>
|
|
44
|
-
)
|
|
45
|
-
else if (props.image === "")
|
|
46
|
-
return (
|
|
47
|
-
<Pressable
|
|
48
|
-
onPress={() => Linking.openURL(props.url)}
|
|
49
|
-
style={styleId_Z1S0WHq} >
|
|
50
|
-
<View style={styleId_Z13iiKo} >
|
|
51
|
-
<Text style={styleId_Z14zkzb} >{props.created.toUpperCase()}</Text>
|
|
52
|
-
<Text numberOfLines={2} ellipsizeMode='tail' style={styleId_1NrPkO} >{props.title}</Text>
|
|
53
|
-
<View style={styleId_Z1i5LUH} >
|
|
54
|
-
<Text style={styleId_mzCdS} >{props.created_by_alias}</Text>
|
|
55
|
-
</View>
|
|
56
|
-
</View>
|
|
57
|
-
</Pressable>
|
|
58
|
-
)
|
|
59
|
-
else
|
|
60
|
-
return (
|
|
61
|
-
<Pressable
|
|
62
|
-
onPress={() => LibNavigation.push('content/detail', { ...props })}
|
|
63
|
-
style={styleId_Z1S0WHq} >
|
|
64
|
-
<Image source={{ uri: props.image }} style={styleId_Zl1hMr} />
|
|
65
|
-
<View style={styleId_Z13iiKo} >
|
|
66
|
-
<Text style={styleId_Z14zkzb} >{props.created.toUpperCase()}</Text>
|
|
67
|
-
<Text numberOfLines={2} ellipsizeMode='tail' style={styleId_1NrPkO} >{props.title}</Text>
|
|
68
|
-
<View style={styleId_Z1i5LUH} >
|
|
69
|
-
<Text style={styleId_mzCdS} >{props.created_by_alias}</Text>
|
|
70
|
-
</View>
|
|
71
|
-
</View>
|
|
72
|
-
</Pressable>
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
<Pressable
|
|
77
|
-
onPress={() => LibNavigation.push('content/detail', { ...props })}
|
|
78
|
-
style={styleId_Z1S0WHq} >
|
|
79
|
-
{
|
|
80
|
-
configlist.thumbnail == 1 &&
|
|
81
|
-
<LibPicture source={{ uri: props.image }} style={styleId_Zl1hMr} />
|
|
82
|
-
}
|
|
83
|
-
<View style={styleId_Z13iiKo} >
|
|
84
|
-
{
|
|
85
|
-
configlist.created == 1 &&
|
|
86
|
-
<Text style={styleId_Z14zkzb} >{LibUtils.moment(props.created, 'id').format('DD MMM YYYY HH:mm').toUpperCase()}</Text>
|
|
87
|
-
}
|
|
88
|
-
{
|
|
89
|
-
configlist.title == 1 &&
|
|
90
|
-
<Text numberOfLines={2} ellipsizeMode='tail' style={styleId_1NrPkO} >{props.title}</Text>
|
|
91
|
-
}
|
|
92
|
-
{
|
|
93
|
-
configlist.author == 1 &&
|
|
94
|
-
<View style={styleId_Z1i5LUH} >
|
|
95
|
-
<Text style={styleId_mzCdS} >{props.created_by_alias}</Text>
|
|
96
|
-
</View>
|
|
97
|
-
}
|
|
98
|
-
</View>
|
|
99
|
-
<Pressable onPress={() => ContentBookmarkProperty.toggle(props)} >
|
|
100
|
-
<LibIcon name={isBook ? 'bookmark' : 'bookmark-plus-outline'} color={'#FD5593'} size={24} />
|
|
101
|
-
</Pressable>
|
|
102
|
-
</Pressable>
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
const styleId_Z1pdPtF: any = { width: LibStyle.width, height: 110, resizeMode: 'contain' }
|
|
106
|
-
const styleId_Z1S0WHq: any = { paddingHorizontal: 16, paddingVertical: 16, flexDirection: 'row', borderBottomWidth: 1, borderTopWidth: 1, borderBottomColor: '#f2f2f2', borderTopColor: '#f8f8f8' }
|
|
107
|
-
const styleId_Z13iiKo: any = { flex: 1, marginLeft: 16, paddingTop: 0 }
|
|
108
|
-
const styleId_Z14zkzb: any = { fontSize: 10, fontWeight: "500", letterSpacing: 1.5, color: "#686868" }
|
|
109
|
-
const styleId_1NrPkO: any = { fontSize: 17, fontWeight: "500", lineHeight: 21, color: "#060606", marginTop: 5, }
|
|
110
|
-
const styleId_Z1i5LUH: any = { flexDirection: 'row', marginTop: 5 }
|
|
111
|
-
const styleId_mzCdS: any = { fontSize: 14, lineHeight: 20, color: LibStyle.colorPrimary, }
|
|
112
|
-
const styleId_Zl1hMr: any = { height: 90, width: 110, borderRadius: 8, backgroundColor: '#f8f8f8' }
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
// noPage
|
|
3
|
-
|
|
4
|
-
import { applyStyle, ContentBookmarkProperty, LibIcon, LibNavigation, LibStyle, LibUtils } from 'esoftplay';
|
|
5
|
-
import { LinearGradient } from 'expo-linear-gradient';
|
|
6
|
-
import React from 'react';
|
|
7
|
-
import { ImageBackground, Pressable, Text, View } from 'react-native';
|
|
8
|
-
|
|
9
|
-
export interface ContentItem_headerArgs {
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
export interface ContentItem_headerProps {
|
|
13
|
-
id: string,
|
|
14
|
-
title: string,
|
|
15
|
-
intro: string,
|
|
16
|
-
description: string,
|
|
17
|
-
image: string,
|
|
18
|
-
created: string,
|
|
19
|
-
updated: string,
|
|
20
|
-
url: string,
|
|
21
|
-
publish: string,
|
|
22
|
-
type_id: string,
|
|
23
|
-
created_by: string,
|
|
24
|
-
created_by_alias: string,
|
|
25
|
-
modified_by: string,
|
|
26
|
-
revised: string,
|
|
27
|
-
hits: string,
|
|
28
|
-
rating: string,
|
|
29
|
-
last_hits: string,
|
|
30
|
-
is_popimage: string,
|
|
31
|
-
is_front: string,
|
|
32
|
-
is_config: string,
|
|
33
|
-
config: string,
|
|
34
|
-
}
|
|
35
|
-
const itemHeight = LibStyle.width * 3 / 4
|
|
36
|
-
export default function m(props: ContentItem_headerProps): any {
|
|
37
|
-
const isBook = ContentBookmarkProperty.state().useSelector(s => s.ids.includes(Number(props.id)))
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<Pressable onPress={() => LibNavigation.push('content/detail', { ...props })} >
|
|
41
|
-
<ImageBackground
|
|
42
|
-
source={{ uri: props.image }}
|
|
43
|
-
style={applyStyle({ height: itemHeight, width: LibStyle.width, justifyContent: 'flex-end' })} >
|
|
44
|
-
<LinearGradient colors={['transparent', 'rgba(0,0,0,0.8)']} style={applyStyle({ padding: 16 })} >
|
|
45
|
-
<Text style={applyStyle({ fontSize: 10, fontWeight: "500", letterSpacing: 1.5, color: "white", textTransform: 'uppercase' })} >{LibUtils.moment(props.created, 'id').format('DD MMM YYYY HH:mm')}</Text>
|
|
46
|
-
<Text style={applyStyle({ fontSize: 24, fontWeight: "500", lineHeight: 30, color: "white", marginTop: 5 })} >{props.title}</Text>
|
|
47
|
-
<View style={applyStyle({ flexDirection: 'row', marginTop: 5 })} >
|
|
48
|
-
<View style={applyStyle({ backgroundColor: 'rgba(255,255,255,0.6)', borderRadius: 4, paddingHorizontal: 10, })} >
|
|
49
|
-
<Text style={applyStyle({ fontSize: 14, lineHeight: 20, color: LibStyle.colorPrimary, })} >{props.created_by_alias}</Text>
|
|
50
|
-
</View>
|
|
51
|
-
</View>
|
|
52
|
-
</LinearGradient>
|
|
53
|
-
<Pressable onPress={() => ContentBookmarkProperty.toggle(props)} style={applyStyle({ position: 'absolute', top: 16, right: 16 })} >
|
|
54
|
-
<LibIcon name={isBook ? 'bookmark' : 'bookmark-plus-outline'} color={'#FD5593'} size={30} />
|
|
55
|
-
</Pressable>
|
|
56
|
-
</ImageBackground>
|
|
57
|
-
</Pressable>
|
|
58
|
-
)
|
|
59
|
-
}
|
package/modules/content/list.tsx
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
|
|
3
|
-
import { ContentCategory_list, ContentConfig, ContentHeader, ContentItem, ContentItem_header, esp, LibCarrousel, LibInfinite, LibNavigation, LibObject, LibStyle, UserRoutes, useSafeState } from 'esoftplay';
|
|
4
|
-
import React, { useRef } from 'react';
|
|
5
|
-
import { View } from 'react-native';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export interface ContentListArgs {
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface ContentListProps {
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
export default function m(props: ContentListProps): any {
|
|
15
|
-
|
|
16
|
-
const routes = UserRoutes.state().get()
|
|
17
|
-
|
|
18
|
-
let { url, title, id } = useRef<any>(LibNavigation.getArgsAll(props)).current
|
|
19
|
-
const conf = esp.config()
|
|
20
|
-
url = url || conf.content
|
|
21
|
-
id = id || 0
|
|
22
|
-
const [data, setData] = useSafeState<any[]>([])
|
|
23
|
-
const [header, setHeader] = useSafeState<any[]>([])
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<View style={{ flex: 1 }} >
|
|
27
|
-
<ContentHeader backButton={routes?.index != undefined && routes?.index > 0} title={title || esp.appjson()?.expo?.name} searchButton />
|
|
28
|
-
<LibInfinite
|
|
29
|
-
url={url}
|
|
30
|
-
injectData={data}
|
|
31
|
-
ListHeaderComponent={
|
|
32
|
-
<>
|
|
33
|
-
<ContentCategory_list id={id} />
|
|
34
|
-
<LibCarrousel
|
|
35
|
-
autoplay
|
|
36
|
-
bullets
|
|
37
|
-
bulletsContainerStyle={{ justifyContent: 'flex-end', marginRight: 10 }}
|
|
38
|
-
chosenBulletStyle={{ width: 8, height: 4, borderRadius: 2, marginHorizontal: 4 }}
|
|
39
|
-
bulletStyle={{ width: 4, height: 4, borderRadius: 2, marginHorizontal: 4 }}
|
|
40
|
-
style={{ height: 3 / 4 * LibStyle.width }}>
|
|
41
|
-
{header.map(item => <ContentItem_header {...item} />)}
|
|
42
|
-
</LibCarrousel>
|
|
43
|
-
</>
|
|
44
|
-
}
|
|
45
|
-
onResult={(res) => {
|
|
46
|
-
ContentConfig.state().set(LibObject.set(ContentConfig.state().get(), res.config)('list'))
|
|
47
|
-
}}
|
|
48
|
-
onDataChange={(data: any[], page) => {
|
|
49
|
-
if (page == 0) {
|
|
50
|
-
setData(LibObject.splice(data, 0, 4)())
|
|
51
|
-
setHeader(data.slice(0, 4).filter((row) => row.created != 'sponsor'))
|
|
52
|
-
} else {
|
|
53
|
-
setData(data)
|
|
54
|
-
}
|
|
55
|
-
}}
|
|
56
|
-
renderItem={(item) => <ContentItem {...item} />}
|
|
57
|
-
/>
|
|
58
|
-
</View>
|
|
59
|
-
)
|
|
60
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// withHooks
|
|
2
|
-
|
|
3
|
-
import { ContentHeader, esp, LibInput, LibNavigation } from 'esoftplay';
|
|
4
|
-
import React, { useRef } from 'react';
|
|
5
|
-
import { View } from 'react-native';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export interface ContentSearchArgs {
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface ContentSearchProps {
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
export default function m(props: ContentSearchProps): any {
|
|
15
|
-
const searchInput = useRef<LibInput>(null)
|
|
16
|
-
const content = esp.config('content')
|
|
17
|
-
|
|
18
|
-
function doSearch() {
|
|
19
|
-
const keyword = encodeURIComponent(searchInput.current?.getText() || '')
|
|
20
|
-
LibNavigation.push('content/list', { title: 'Cari untuk ' + keyword, url: content + 'search.htm?id=' + keyword })
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<View>
|
|
25
|
-
<ContentHeader title="Cari Artikel" backButton />
|
|
26
|
-
<LibInput base
|
|
27
|
-
ref={searchInput}
|
|
28
|
-
autoFocus
|
|
29
|
-
placeholder={"Cari artikel"}
|
|
30
|
-
returnKeyType="search"
|
|
31
|
-
onChangeText={(text) => { }}
|
|
32
|
-
onSubmitEditing={() => doSearch()}
|
|
33
|
-
style={{ flex: 1, minHeight: 40, paddingHorizontal: 8, borderRadius: 8, backgroundColor: '#f5f5f5', marginVertical: 16, marginHorizontal: 16 }}
|
|
34
|
-
/>
|
|
35
|
-
</View>
|
|
36
|
-
)
|
|
37
|
-
}
|