Skip to content

Commit

Permalink
Merge pull request functionland#189 from ghorbani-m/main
Browse files Browse the repository at this point in the history
Box integration is done
  • Loading branch information
ghorbani-m authored Jun 6, 2022
2 parents e244870 + 5c9b696 commit cd15a24
Show file tree
Hide file tree
Showing 34 changed files with 1,003 additions and 89 deletions.
6 changes: 3 additions & 3 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ android {
applicationId "land.fx.fotos"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 3
versionName "0.3.0"
versionCode 4
versionName "0.4.0"
}
splits {
abi {
Expand Down Expand Up @@ -228,7 +228,7 @@ dependencies {
}
}

implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
Expand Down
5 changes: 5 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="land.fx.fotos">

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name="land.fx.fotos.MainApplication"
android:label="@string/app_name"
Expand All @@ -24,5 +28,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.asterinet.react.bgactions.RNBackgroundActionsTask" />
</application>
</manifest>
4 changes: 4 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ allprojects {
repositories {
google()
mavenCentral()
maven {
// react-native-background-fetch
url("${project(':react-native-background-fetch').projectDir}/libs")
}
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
Expand Down
28 changes: 25 additions & 3 deletions app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
import "./i18n"
import "./utils/ignore-warnings"
import React from "react"
import React, { useRef } from "react"
import { useColorScheme } from "react-native"
import { GestureHandlerRootView } from "react-native-gesture-handler"
import { SafeAreaProvider, initialWindowMetrics } from "react-native-safe-area-context"
Expand All @@ -26,6 +26,9 @@ import { ErrorBoundary } from "./screens/error/error-boundary"
import * as MediaLibrary from "expo-media-library"
import { ThemeProvider } from './theme';
import { RneLightTheme, RneDarkTheme } from "./theme"
import NetInfo from "@react-native-community/netinfo";
import { AddBoxs, uploadAssetsInBackground } from "./services/sync-service"
import { SyncService } from "./services"

// This puts screens in a native ViewController or Activity. If you want fully native
// stack navigation, use `createNativeStackNavigator` in place of `createStackNavigator`:
Expand All @@ -39,7 +42,7 @@ export const NAVIGATION_PERSISTENCE_KEY = "NAVIGATION_STATE"

function App() {
const scheme = useColorScheme();

const netInfoTimer = useRef(null);
useBackButtonHandler(canExit)
const { onNavigationStateChange, isRestored: isNavigationStateRestored } =
useNavigationPersistence(storage, NAVIGATION_PERSISTENCE_KEY)
Expand All @@ -50,8 +53,27 @@ function App() {
; (async () => {
await getPermissions()
await initFonts()
})()
await SyncService.initBackgroundFetch();
})();
// Subscribe
const unsubscribeNetInfo = subscribeNetInfo();
return () => {
// Unsubscribe
unsubscribeNetInfo();
}
}, [])
const subscribeNetInfo = () => {
return NetInfo.addEventListener(state => {
if (netInfoTimer.current)
clearTimeout(netInfoTimer.current);
netInfoTimer.current = setTimeout(async () => {
if (state.isConnected)
await AddBoxs();
uploadAssetsInBackground();
}, 1000);
});
}


// Before we show the app, we have to wait for our state to be ready.
// In the meantime, don't render anything. This will be the background
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import React, { memo } from "react"
import { StyleSheet, View, Image, NativeSyntheticEvent, ImageErrorEventData } from "react-native"
import { Icon, Text, useTheme } from "@rneui/themed"

import { Asset } from "../../../../types"
import { Checkbox } from "../../../checkbox/checkbox"

import Animated, { useSharedValue, useAnimatedStyle, withTiming } from "react-native-reanimated"
import { SharedElement } from "react-navigation-shared-element"
import { convertDurationToTime } from "../../../../utils/helper"

interface Props {
asset: Asset
selected: boolean
selectionMode: boolean
selectionMode: boolean,
isSynced: boolean,
isDeleted: boolean,
onError?: (error: NativeSyntheticEvent<ImageErrorEventData>) => void
}
const AssetItem = (props: Props): JSX.Element => {
Expand Down Expand Up @@ -39,13 +41,14 @@ const AssetItem = (props: Props): JSX.Element => {
scaleSharedValue.value = 1
}
}, [selected])

return (
<View style={[styles.container, {
backgroundColor: theme.colors.grey5,
borderColor: theme.colors.background
}]}>
<Animated.View style={[styles.imageContainer, imageContainerAnimatedStyle]}>
<SharedElement style={styles.sharedElementContainer} id={asset.uri}>
{props?.isDeleted && props?.isSynced ? <Icon type="material-community" name="alpha-f-box-outline" size={50} color="gray" /> : <SharedElement style={styles.sharedElementContainer} id={asset.uri}>
<Image
style={styles.image}
source={{
Expand All @@ -55,13 +58,17 @@ const AssetItem = (props: Props): JSX.Element => {
resizeMode="cover"
onError={props.onError}
/>
</SharedElement>
</SharedElement>}
</Animated.View>
{asset?.mediaType === "video" &&
<View style={styles.videoIconContainer}>
<Text style={styles.videoDurationText}>{convertDurationToTime(asset?.duration)}</Text>
<Icon name="play-circle" type="material-community" size={20} color="gray" />
</View>}
{props?.isSynced &&
<View style={styles.syncIconContainer}>
<Icon name="cloud-check" type="material-community" size={15} color="gray" />
</View>}
{selectionMode ? <Checkbox value={selected} style={styles.checkbox} /> : null}
</View>
)
Expand All @@ -87,31 +94,51 @@ const styles = StyleSheet.create({
flex: 1,
overflow: "hidden",
zIndex: 0,
justifyContent:"center"
},
sharedElementContainer: {
flex: 1,
justifyContent: "center"
},
videoIconContainer: {
right: 10,
position: "absolute",
top: 10,
bottom: 10,
zIndex: 99,
flexDirection: "row",
justifyContent: "center",
alignItems: "center"
alignItems: "center",
backgroundColor: "white",
borderRadius: 5,
opacity: .8
},
videoDurationText: {
color: "gray",
fontSize: 10,
padding: 1
}
},
syncIconContainer: {
right: 10,
position: "absolute",
top: 10,
zIndex: 99,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
backgroundColor: "white",
borderRadius: 5,
padding: 1,
opacity: .7
},
})

const areEqual = (prev: Props, next: Props) => {
return (
prev?.asset?.id === next?.asset?.id &&
prev?.selectionMode === next?.selectionMode &&
prev?.selected === next?.selected
prev?.selected === next?.selected &&
prev?.isSynced === next?.isSynced &&
prev?.isDeleted === next?.isDeleted
)
}
export default memo(AssetItem, areEqual)
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from "react"
import { TouchableHighlight, StyleSheet, NativeSyntheticEvent, ImageErrorEventData } from "react-native"
import { GroupHeader, RecyclerAssetListSection, ViewType } from "../../../../types"
import { Asset, GroupHeader, RecyclerAssetListSection, SyncStatus, ViewType } from "../../../../types"
import StoryListItem from "./story-list-item"
import AssetItem from "./asset-item"
import HeaderItem from "./header-item"

interface Props {
section: RecyclerAssetListSection
selectionMode: boolean
selected: boolean
selected: boolean,
onLongPress: (section: RecyclerAssetListSection) => void
onPress: (section: RecyclerAssetListSection) => void
onAssetLoadError?: (error: NativeSyntheticEvent<ImageErrorEventData>) => void
Expand All @@ -24,7 +24,14 @@ const getSectionByType = (
return <StoryListItem stories={section.data} selectionMode={selectionMode} />
}
case ViewType.ASSET: {
return <AssetItem onError={onAssetLoadError} asset={section.data} selectionMode={selectionMode} selected={selected} />
const data = section?.data as Asset
return <AssetItem
onError={onAssetLoadError}
asset={section.data}
selectionMode={selectionMode}
selected={selected}
isSynced={data.syncStatus === SyncStatus.SYNCED}
isDeleted={section?.data?.isDeleted} />
}
case ViewType.MONTH: {
const groupHeader: GroupHeader = section.data
Expand Down
7 changes: 6 additions & 1 deletion app/components/photo-screen-header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@ export const PhotoScreenHeader: React.FC<PhotoScreenHeaderProps> = ({ goBack })
<TouchableNativeFeedback onPress={goBack}>
<Icon name="arrowleft" size={28} style={{ color: palette.white }} />
</TouchableNativeFeedback>
<TouchableNativeFeedback onPress={goBack}>
<Icon name="cloud" size={28} style={{ color: palette.white }} />
</TouchableNativeFeedback>
</View>
)
}

const styles = StyleSheet.create({
container: {
flexDirection:"row",
paddingTop:30,
height: Constants.HeaderHeight,
justifyContent: "center",
justifyContent: "space-between",
paddingHorizontal: 15,
position: "absolute",
width: widthPercentageToDP(100),
Expand Down
4 changes: 2 additions & 2 deletions app/components/screen/screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function ScreenWithoutScrolling(props: ScreenProps) {
keyboardVerticalOffset={offsets[props.keyboardOffset || "none"]}
>
<StatusBar barStyle={props.statusBar || "light-content"} />
<View style={[preset.inner, style, insetStyle]}>{props.children}</View>
<View style={[preset.inner, style, insetStyle,props.style || {}]}>{props.children}</View>
</KeyboardAvoidingView>
)
}
Expand All @@ -42,7 +42,7 @@ function ScreenWithScrolling(props: ScreenProps) {
<StatusBar barStyle={props.statusBar || "light-content"} />
<View style={[preset.outer, backgroundStyle, insetStyle]}>
<ScrollView
style={[preset.outer, backgroundStyle]}
style={[preset.outer, { backgroundColor: theme.colors.background, }, backgroundStyle]}
contentContainerStyle={[preset.inner, style]}
keyboardShouldPersistTaps={props.keyboardShouldPersistTaps || "handled"}
>
Expand Down
33 changes: 24 additions & 9 deletions app/navigators/app-navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@ import Animated from "react-native-reanimated"
import { enableScreens } from "react-native-screens"
import { NavigationContainer } from "@react-navigation/native"
import { createSharedElementStackNavigator } from "react-navigation-shared-element"
import Toast from 'react-native-toast-message'

import { navigationRef } from "./navigation-utilities"
import { PhotoScreen, LibraryAssetsScreen } from "../screens"
import { PhotoScreen, LibraryAssetsScreen, BoxListScreen, BoxAddUpdateScreen } from "../screens"
import { HomeNavigator } from "./home-navigator"
import { ThemeContext } from '../theme';
import { BoxEntity } from "../realmdb/entities"
enableScreens()
export type NavigatorParamList = {
home: undefined
photo: { section: RecyclerAssetListSection }
settings: undefined
export type RootStackParamList = {
Home: undefined
Photo: { section: RecyclerAssetListSection }
Settings: undefined,
BoxList: undefined,
BoxAddUpdate: { box: BoxEntity }
}
export enum AppNavigationNames {
HomeScreen = "home",
PhotoScreen = "photo",
LibraryAssets = "LibraryAssets"
HomeScreen = "Home",
PhotoScreen = "Photo",
LibraryAssets = "LibraryAssets",
BoxList = "BoxList",
BoxAddUpdate = "BoxAddUpdate"
}
const Stack = createSharedElementStackNavigator<NavigatorParamList>()
const Stack = createSharedElementStackNavigator<RootStackParamList>()

const AppStack = () => {
return (
Expand All @@ -38,6 +44,14 @@ const AppStack = () => {
name={AppNavigationNames.LibraryAssets}
component={LibraryAssetsScreen}
/>
<Stack.Screen
name={AppNavigationNames.BoxList}
component={BoxListScreen}
/>
<Stack.Screen
name={AppNavigationNames.BoxAddUpdate}
component={BoxAddUpdateScreen}
/>
<Stack.Screen
name={AppNavigationNames.PhotoScreen}
options={{
Expand Down Expand Up @@ -90,6 +104,7 @@ export const AppNavigator = (props: NavigationProps) => {
>
<AppStack />
</NavigationContainer>
<Toast/>
</Animated.View>
)
}
Expand Down
8 changes: 7 additions & 1 deletion app/realmdb/entities/asset.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { SyncStatus } from "../../types"

export type AssetEntity = {
id: string
/**
Expand Down Expand Up @@ -43,7 +45,7 @@ export type AssetEntity = {
/**
* Sync statis with box
*/
isSynced: boolean
syncStatus: SyncStatus
/**
* Sync date with box
*/
Expand All @@ -52,4 +54,8 @@ export type AssetEntity = {
* content id in the box
*/
cid: string | undefined
/**
* Deleted from storage
*/
isDeleted: boolean
}
19 changes: 19 additions & 0 deletions app/realmdb/entities/box.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export type BoxEntity = {
/**
* Box peerId
*/
peerId: string
/**
* box nickname.
*/
name: string | undefined
/**
* Box address
*/
address: string | undefined

/**
* Determin the default device for connectio
*/
isDefault: boolean
}
Loading

0 comments on commit cd15a24

Please sign in to comment.