Skip to content

Commit 7e7c626

Browse files
authored
Merge pull request #5 from akshay9/feature/favourites
Added Sub-Categories for photos
2 parents 8816646 + a676acb commit 7e7c626

File tree

16 files changed

+397
-113
lines changed

16 files changed

+397
-113
lines changed

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ android {
135135
applicationId "com.librephotosmobile"
136136
minSdkVersion rootProject.ext.minSdkVersion
137137
targetSdkVersion rootProject.ext.targetSdkVersion
138-
versionCode 1
139-
versionName "1.0"
138+
versionCode 2
139+
versionName "1.0.1"
140140
}
141141
splits {
142142
abi {

app.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"name": "LibrePhotosMobile",
33
"displayName": "LibrePhotosMobile",
4-
"version": "1.0.0"
4+
"version": "1.0.1"
55
}

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
{
22
"name": "librephotosmobile",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"private": true,
55
"scripts": {
66
"android": "react-native run-android",
77
"ios": "react-native run-ios",
88
"start": "react-native start",
99
"test": "jest",
1010
"lint": "eslint .",
11-
"type-check": "tsc --build plugins/typescript/template/tsconfig.json"
11+
"type-check": "tsc --build plugins/typescript/template/tsconfig.json",
12+
"postversion": "react-native-version"
1213
},
1314
"dependencies": {
1415
"@dudigital/react-native-zoomable-view": "^1.1.3",
@@ -59,6 +60,7 @@
5960
"identity-obj-proxy": "^3.0.0",
6061
"jest": "^26.6.3",
6162
"metro-react-native-babel-preset": "^0.64.0",
63+
"react-native-version": "^4.0.0",
6264
"react-test-renderer": "17.0.1"
6365
},
6466
"jest": {

src/Components/ImageGrid.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ const ImageGrid = ({
5757
</Pressable>
5858
)
5959
}
60-
6160
return (
6261
<>
6362
{data && data.length > 0 && (
@@ -70,9 +69,12 @@ const ImageGrid = ({
7069
renderItem={renderPhoto}
7170
/>
7271
)}
73-
{(typeof data === 'undefined' || data.length < 1) && displayError && (
74-
<NoResultsError refreshing={refreshing} onRefresh={onRefresh} />
75-
)}
72+
{(typeof data !== 'object' ||
73+
typeof data.length === 'undefined' ||
74+
data.length < 1) &&
75+
displayError && (
76+
<NoResultsError refreshing={refreshing} onRefresh={onRefresh} />
77+
)}
7678

7779
<Modal
7880
animationType="fade"

src/Components/NoResultsError.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react'
22
import { RefreshControl } from 'react-native'
3-
import { Icon, ScrollView, Text, View } from 'native-base'
3+
import { Icon, ScrollView, Text } from 'native-base'
44
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
55
import { useTheme } from '@/Theme'
66

src/Components/PreviewTile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ const PreviewTile = ({
111111
<FlatList
112112
// refreshing={false}
113113
// onRefresh={() => {}}
114+
showsHorizontalScrollIndicator={false}
114115
data={albums}
115116
renderItem={renderItem}
116117
horizontal={true}

src/Containers/Gallery/Index.js

Lines changed: 130 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
import React, { useEffect, useState } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
33
import { View } from 'react-native'
4-
import { Button, HStack } from 'native-base'
4+
import { Button, HStack, ScrollView } from 'native-base'
55
import { useTheme } from '@/Theme'
66
import FetchAlbumByDate from '@/Store/Album/FetchByDate'
77
import FetchPhotosWithoutDate from '@/Store/Album/FetchPhotosWithoutDate'
8-
import TimelineList from '../../Components/TimelineList'
9-
import { TopBar } from '../../Components'
10-
import ImageGrid from '../../Components/ImageGrid'
8+
import FetchRecentlyAdded from '@/Store/Album/FetchRecentlyAdded'
9+
import FetchFavourites from '@/Store/Album/FetchFavourites'
10+
import FetchHidden from '@/Store/Album/FetchHidden'
11+
import FetchPublic from '@/Store/Album/FetchPublic'
12+
import TimelineList from '@/Components/TimelineList'
13+
import { TopBar } from '@/Components'
14+
import ImageGrid from '@/Components/ImageGrid'
15+
16+
const CategoryType = {
17+
PhotosByDate: 'With Timestamp',
18+
PhotosWithoutDate: 'Without Timestamp',
19+
Recent: 'Recently Added',
20+
Favourite: 'Favourites',
21+
Public: 'Public Photos',
22+
Hidden: 'Hidden',
23+
}
1124

1225
const GalleryContainer = () => {
1326
const { Common, Layout } = useTheme()
@@ -16,108 +29,136 @@ const GalleryContainer = () => {
1629
const albums = useSelector(state => state.album)
1730
const albumByDate = useSelector(state => state.album.albumByDate)
1831
const albumWithoutDate = useSelector(state => state.album.albumWithoutDate)
19-
const photosByDate = albumByDate?.results
32+
const albumRecentlyAdded = useSelector(
33+
state => state.album.albumRecentlyAdded,
34+
)
35+
const albumFavourites = useSelector(state => state.album.albumFavourites)
36+
const albumPublic = useSelector(state => state.album.albumPublic)
37+
const albumHidden = useSelector(state => state.album.albumHidden)
38+
const photosByDate = albumByDate
2039
const photosWithoutDate = albumWithoutDate?.results
2140

22-
useEffect(() => {
23-
handleAlbumWithoutDateRefresh()
24-
handleAlbumWithDateRefresh()
25-
// eslint-disable-next-line react-hooks/exhaustive-deps
26-
}, [])
27-
28-
const handleAlbumWithoutDateRefresh = () => {
29-
dispatch(FetchPhotosWithoutDate.action())
30-
}
31-
32-
const handleAlbumWithDateRefresh = () => {
33-
dispatch(FetchAlbumByDate.action())
34-
}
35-
36-
const imageGridMapper = sectionData => {
37-
if (typeof sectionData === 'undefined' || sectionData.length < 1) {
38-
return []
39-
}
40-
41-
let finalmap = sectionData.map(item => {
42-
return {
43-
url: item.url,
44-
}
45-
})
46-
47-
return finalmap
48-
}
41+
const [category, setCategory] = useState(CategoryType.PhotosByDate)
4942

50-
const photoMapper = photosResult => {
51-
if (typeof photosResult === 'undefined' || photosResult.length < 1) {
52-
return []
43+
useEffect(() => {
44+
console.log('Fetching Category: ' + category)
45+
switch (category) {
46+
case CategoryType.PhotosByDate:
47+
dispatch(FetchPhotosWithoutDate.action())
48+
break
49+
case CategoryType.PhotosWithoutDate:
50+
dispatch(FetchAlbumByDate.action())
51+
break
52+
case CategoryType.Recent:
53+
dispatch(FetchRecentlyAdded.action())
54+
break
55+
case CategoryType.Favourite:
56+
dispatch(FetchFavourites.action())
57+
break
58+
case CategoryType.Public:
59+
dispatch(FetchPublic.action())
60+
break
61+
case CategoryType.Hidden:
62+
dispatch(FetchHidden.action())
63+
break
5364
}
65+
}, [dispatch, category])
5466

55-
let finalmap = photosResult.map(item => {
56-
return {
57-
id: item.date,
58-
title: item.date,
59-
data: imageGridMapper(item.items),
60-
}
61-
})
67+
useEffect(() => {
68+
dispatch(FetchAlbumByDate.action())
69+
// eslint-disable-next-line react-hooks/exhaustive-deps
70+
}, [])
6271

63-
return finalmap
72+
const renderButton = (index, buttonCategory) => {
73+
return (
74+
<Button
75+
key={index}
76+
size="xs"
77+
variant={category === buttonCategory ? 'solid' : 'outline'}
78+
colorScheme="dark"
79+
onPress={() => setCategory(buttonCategory)}
80+
>
81+
{buttonCategory}
82+
</Button>
83+
)
6484
}
6585

66-
const [showPhotosByDate, setPhotosByDate] = useState(true)
67-
68-
return (
69-
<>
70-
<TopBar />
71-
<View style={[Common.backgroundDefault, Layout.colCenter]}>
72-
<HStack
73-
space={{
74-
base: 3,
75-
md: 4,
76-
}}
77-
mx={{
78-
base: 5,
79-
md: 0,
80-
}}
81-
my={{
82-
base: 2,
83-
md: 0,
84-
}}
85-
style={[Common.backgroundDefault]}
86-
>
87-
<Button
88-
size="xs"
89-
variant={showPhotosByDate ? 'solid' : 'outline'}
90-
colorScheme="dark"
91-
onPress={() => setPhotosByDate(true)}
92-
>
93-
With Timestamp
94-
</Button>
95-
<Button
96-
size="xs"
97-
variant={!showPhotosByDate ? 'solid' : 'outline'}
98-
colorScheme="dark"
99-
onPress={() => setPhotosByDate(false)}
100-
>
101-
Without Timestamp
102-
</Button>
103-
</HStack>
104-
</View>
105-
<View style={[Layout.fill, Layout.colCenter, Common.backgroundDefault]}>
106-
{showPhotosByDate ? (
86+
const renderContent = () => {
87+
switch (category) {
88+
case CategoryType.PhotosByDate:
89+
return (
10790
<TimelineList
108-
data={photoMapper(photosByDate)}
109-
onRefresh={handleAlbumWithDateRefresh}
91+
data={photosByDate}
92+
onRefresh={() => dispatch(FetchAlbumByDate.action())}
11093
refreshing={albums.loading}
11194
/>
112-
) : (
95+
)
96+
case CategoryType.PhotosWithoutDate:
97+
return (
11398
<ImageGrid
11499
data={photosWithoutDate}
115100
numColumns={3}
116101
displayError={true}
117-
onRefresh={handleAlbumWithoutDateRefresh}
102+
onRefresh={() => dispatch(FetchPhotosWithoutDate.action())}
103+
refreshing={albums.loading}
104+
/>
105+
)
106+
case CategoryType.Recent:
107+
return (
108+
<ImageGrid
109+
data={albumRecentlyAdded?.results}
110+
numColumns={3}
111+
displayError={true}
112+
onRefresh={() => dispatch(FetchAlbumByDate.action())}
113+
refreshing={albums.loading}
114+
/>
115+
)
116+
case CategoryType.Favourite:
117+
return (
118+
<TimelineList
119+
data={albumFavourites}
120+
onRefresh={() => dispatch(FetchFavourites.action())}
121+
refreshing={albums.loading}
122+
/>
123+
)
124+
case CategoryType.Public:
125+
return (
126+
<TimelineList
127+
data={albumPublic}
128+
onRefresh={() => dispatch(FetchPublic.action())}
129+
refreshing={albums.loading}
130+
/>
131+
)
132+
case CategoryType.Hidden:
133+
return (
134+
<TimelineList
135+
data={albumHidden}
136+
onRefresh={() => dispatch(FetchHidden.action())}
118137
refreshing={albums.loading}
119138
/>
120-
)}
139+
)
140+
}
141+
}
142+
143+
return (
144+
<>
145+
<TopBar />
146+
<View style={[Common.backgroundDefault, Layout.colCenter]}>
147+
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
148+
<HStack
149+
space={{ base: 3, md: 4 }}
150+
mx={{ base: 5, md: 0 }}
151+
my={{ base: 2, md: 0 }}
152+
style={[Common.backgroundDefault]}
153+
>
154+
{Object.values(CategoryType).map((buttonCategory, index) =>
155+
renderButton(index, buttonCategory),
156+
)}
157+
</HStack>
158+
</ScrollView>
159+
</View>
160+
<View style={[Layout.fill, Common.backgroundDefault]}>
161+
{renderContent()}
121162
</View>
122163
</>
123164
)

src/Containers/Settings/Index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { SettingSubHeader } from './SettingSubHeader'
1010
import { OptionMultiSelect } from './OptionMultiSelect'
1111
import { OptionButton } from './OptionButton'
1212
import LogoutUser from '@/Store/Auth/LogoutUser'
13-
import { version } from '../../../app.json'
13+
import { version } from '../../../package.json'
1414
import UpdateToken from '../../Services/Auth/UpdateToken'
1515
import ConfigureLogging from '../../Store/Config/ConfigureLogging'
1616
import { OptionToggle } from './OptionToggle'

src/Store/Album/FetchByDate.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
buildAsyncReducers,
55
} from '@thecodingmachine/redux-toolkit-wrapper'
66
import api from '@/Services'
7+
import { photoMapper } from '../../Services/DataMapper/PhotosByDate'
78

89
export default {
910
initialState: buildAsyncState(),
@@ -13,7 +14,7 @@ export default {
1314
timeout: 10000,
1415
})
1516
.then(response => {
16-
return response.data
17+
return photoMapper(response.data?.results)
1718
})
1819
}),
1920
reducers: buildAsyncReducers({ itemKey: 'albumByDate' }), // We do not want to modify some item by default

src/Store/Album/FetchFavourites.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {
2+
buildAsyncState,
3+
buildAsyncActions,
4+
buildAsyncReducers,
5+
} from '@thecodingmachine/redux-toolkit-wrapper'
6+
import api from '@/Services'
7+
import { photoMapper } from '../../Services/DataMapper/PhotosByDate'
8+
9+
export default {
10+
initialState: buildAsyncState(),
11+
action: buildAsyncActions('album/fetchFavourites', async (args, k) => {
12+
return await api
13+
.get('/photos/favorites/', {
14+
timeout: 10000,
15+
})
16+
.then(response => {
17+
return photoMapper(response.data?.results)
18+
})
19+
}),
20+
reducers: buildAsyncReducers({ itemKey: 'albumFavourites' }), // We do not want to modify some item by default
21+
}

0 commit comments

Comments
 (0)