adding nano sante

This commit is contained in:
bricezele 2021-02-25 19:47:49 +01:00
parent 7c35fce031
commit a40786c779
164 changed files with 30087 additions and 379 deletions

View File

@ -6,9 +6,17 @@
* @flow
*/
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, YellowBox } from 'react-native';
import { createSwitchNavigator, createStackNavigator, createDrawerNavigator, createAppContainer, createBottomTabNavigator } from 'react-navigation';
import React from 'react';
import {ActionSheetProvider} from '@expo/react-native-action-sheet'
import {AsyncStorage, Platform, StyleSheet} from 'react-native';
import {
createAppContainer,
createBottomTabNavigator,
createDrawerNavigator,
createStackNavigator,
createSwitchNavigator
} from 'react-navigation';
import OneSignal from 'react-native-onesignal';
import Connect from "./screens/login/Connect";
import SplashScreen from "./screens/splashscreen/SplashScreen";
import HelpMenu from "./screens/help/HelpMenu";
@ -23,8 +31,6 @@ import ActivateAccount from "./screens/login/ActivateAccount";
import Notifications from "./screens/notifications/Notifications";
import About from "./screens/configurations/About";
import Configurations from "./screens/configurations/Configurations";
import History from './screens/history-request/History'
import OptionsMenu from "./screens/optionMenu/OptionsMenu";
import Home from "./screens/home/Home";
import HistoryItemDetails from "./screens/history-request/HistoryItemDetails";
@ -33,235 +39,525 @@ import HistoryRequester from "./screens/history-request/HistoryRequester";
import AddNetwork from "./screens/account/AddNetwork";
import MyHistory from "./screens/history-request/MyHistory";
import Icon from "react-native-vector-icons/FontAwesome5";
import { Appbar } from 'react-native-paper';
import IconWithBadge from "./screens/IconWithBadge"
import I18n from "react-native-i18n";
import Filter from './screens/home/Filter';
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';
import Networks from './screens/home/Networks';
import WalletDetail from './screens/wallet/WalletDetail';
import WalletSelect from './screens/wallet/WalletSelect';
import {PersistGate} from 'redux-persist/integration/react';
import {persistor, store} from './redux/store';
import {Provider} from 'react-redux';
import WalletDepot from './screens/wallet/WalletDepot';
import WalletRetrait from './screens/wallet/WalletRetrait';
import CreateIdentification from './screens/identification/createIdentification';
import WalletDetailUser from './screens/wallet/WalletDetailUser';
import WalletOptionSelect from './screens/wallet/WalletOptionSelect';
import ValidateIdentification from './screens/identification/validateIdentification';
import CreateIdentificationUser from './screens/identification/CreateIdentificationUser';
import OperateurOptionSelect from './screens/wallet/OperateurOptionSelect';
import PaiementFacture from './screens/wallet/PaiementFacture';
import EnvoieWalletToWalletUser from './screens/wallet/user/EnvoieWalletToWalletUser';
import EnvoieWalletToCashUser from './screens/wallet/user/EnvoieWalletToCash';
import LinkCard from './screens/wallet/user/LinkCard';
import EnvoieWalletToCardUser from './screens/wallet/user/EnvoieWalletToCardUser';
import EnvoieWalletToBankUser from './screens/wallet/user/EnvoieWalletToBankUser';
import RetraitWalletVersCashUser from './screens/wallet/user/RetraitWalletVersCashUser';
import RetraitCarteVersCashUser from './screens/wallet/user/RetraitCarteVersCashUser';
import RetraitCarteVersWalletUser from './screens/wallet/user/RetraitCarteVersWalletUser';
import RetraitEnCashAgent from './screens/wallet/agent/RetraitEnCashAgent';
import RetraitCarteVersCashAgent from './screens/wallet/agent/RetraitCarteVersCashAgent';
import EnvoieCashVersWalletAgent from './screens/wallet/agent/EnvoieCashVersWalletAgent';
import EnvoieCashVersAutreWalletAgent from './screens/wallet/agent/EnvoieCashVersAutreWalletAgent';
import EnvoieCashVersCarteAgent from './screens/wallet/agent/EnvoieCashVersCarteAgent';
import EnvoiCashVersCashAgent from './screens/wallet/agent/EnvoiCashVersCashAgent';
import ModifyIdentificationUser from './screens/identification/ModifyIdentificationUser';
import CreateGroupNanoCredit from './screens/nano-credit/CreateGroupNanoCredit';
import DemandValidationGroup from './screens/nano-credit/DemandGroupNanoCredit';
import DemandGroupNanoCreditDetail from './screens/nano-credit/DemandGroupNanoCreditDetail';
import AdhererGroupNanoCredit from './screens/nano-credit/AdhererGroupNanoCredit';
import MyNanoCreditGroup from './screens/nano-credit/MyNanoCreditGroup';
import AskNanoCredit from './screens/nano-credit/AskNanoCredit';
import RefundNanoCreditUser from './screens/nano-credit/RefundNanoCreditUser';
import CautionNanoCreditAgent from './screens/nano-credit/CautionNanoCreditAgent';
import EpargnerArgentUser from './screens/nano-credit/EpargnerArgentUser';
import CasserEpargneUser from './screens/nano-credit/CasserEpargneUser';
import {IlinkEmitter} from './utils/events';
import EnvoieWalletToBankAgent from "./screens/wallet/agent/EnvoieWalletToBankAgent";
import ReattachAccountUser from "./screens/wallet/user/ReattachAccountUser";
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
type Props = {};
const theme = require("./utils/theme")
class HomeScreen extends Component<Props> {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to iLink World!</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Text style={styles.instructions}>{instructions}</Text>
</View>
);
}
}
const AuthStack = createStackNavigator({
login: Connect,
helpMenu: HelpMenu,
help: Help,
forgottenpass: ForgottenPassword,
typeaccountcreate: TypeChoiser,
simpleusercreate: createAccount,
step2: CreateUserStep2,
activateaccout: ActivateAccount
login: Connect,
helpMenu: HelpMenu,
help: Help,
forgottenpass: ForgottenPassword,
typeaccountcreate: TypeChoiser,
simpleusercreate: createAccount,
step2: CreateUserStep2,
activateaccout: ActivateAccount
}, {
headerMode: 'none'
headerMode: 'none'
})
const AppStack = createDrawerNavigator({
sta: createStackNavigator({
home: Home,
/* filtre:Filter,
network:Networks,*/
useraccount: {
screen: UserAccount,
navigationOptions: {
},
},
notificationview: Notifications,
configuration: Configurations,
about: About
sta: createStackNavigator({
home: Home,
/* filtre:Filter,
network:Networks,*/
useraccount: {
screen: UserAccount,
navigationOptions: {},
},
walletSelect: WalletSelect,
createIdentificationUser: CreateIdentificationUser,
modifyIdentificationUser: ModifyIdentificationUser,
notificationview: Notifications,
configuration: Configurations,
about: About,
walletDetailUser: WalletDetailUser,
walletOptionSelect: WalletOptionSelect,
operateurOptionSelect: OperateurOptionSelect,
paiementFacture: PaiementFacture,
envoieWalletToWalletUser: EnvoieWalletToWalletUser,
envoieWalletToCashUser: EnvoieWalletToCashUser,
envoieWalletToCardUser: EnvoieWalletToCardUser,
envoieWalletToBankUser: EnvoieWalletToBankUser,
retraitWalletVersCashUser: RetraitWalletVersCashUser,
retraitCarteVersCashUser: RetraitCarteVersCashUser,
retraitCarteVersWalletUser: RetraitCarteVersWalletUser,
linkCard: LinkCard,
reattachAccountUser: ReattachAccountUser,
epargnerArgentUser: EpargnerArgentUser,
createGroupNanoCredit: CreateGroupNanoCredit,
groupNanoCredit: {
screen: createBottomTabNavigator({
demandeValidationGroupe: {
screen: DemandValidationGroup,
navigationOptions: {
tabBarLabel: I18n.t('DEMAND_VALIDATION_GROUP_RECEIVE'),
tabBarIcon: ({focused, horizontal, tintColor}) => {
return (<Icon
size={20}
name={"users-cog"}
color={focused ? tintColor : "grey"}
/>)
}
}
},
myNanoCreditGroup: {
screen: MyNanoCreditGroup,
navigationOptions: {
tabBarLabel: I18n.t('MY_GROUP'),
tabBarIcon: ({focused, horizontal, tintColor}) => {
return (<Icon
size={20}
name={"users"}
color={focused ? tintColor : "grey"}
/>)
}
}
},
}, {
headerMode: "none",
header: null,
headerTitle: null,
title: I18n.t('MANAGE_GROUP'),
tabBarOptions: {
labelStyle: {
fontSize: 13,
},
}
}),
navigationOptions: () => ({
header: null,
headerMode: 'none',
headerTitle: null,
activeColor: '#f0edf6',
inactiveColor: '#3e2465',
barStyle: {backgroundColor: '#694fad'},
drawerLabel: I18n.t('MANAGE_GROUP'),
drawerIcon: ({tintColor}) => (
<Icon
name={'account-multiple'}
size={24}
/>)
}),
},
demandeValidationGroupe: DemandGroupNanoCreditDetail,
adhererGroupNanoCredit: AdhererGroupNanoCredit,
askNanoCredit: AskNanoCredit,
refundNanoCreditUser: RefundNanoCreditUser,
casserEpargneUser: CasserEpargneUser
})
}, {
contentComponent: OptionsMenu,
headerMode: 'none',
contentOptions: {activeTintColor: theme.accent}
})
})
}, { contentComponent: OptionsMenu, headerMode: 'none', contentOptions: { activeTintColor: theme.accent } })
const AppAgentStack = createDrawerNavigator({
sta: createStackNavigator({
home: Home,
useraccount: UserAccount,
Historique:
{
screen: createBottomTabNavigator({ myDemand: MyHistory }, {
sta: createStackNavigator({
home: Home,
useraccount: UserAccount,
walletSelect: WalletSelect,
createIdentification: CreateIdentification,
validateIdentification: ValidateIdentification,
Historique:
{
screen: createBottomTabNavigator({myDemand: MyHistory}, {
headerMode: "none",
header: null,
headerTitle: null,
headerTitle: I18n.t('CREDIT_MANAGE'),
tabBarOptions: {
labelStyle: {
fontSize: 13,
fontWeight: "bold"
},
labelStyle: {
fontSize: 13,
fontWeight: "bold"
},
}
}),
navigationOptions: ({ navigation }) => ({
}),
navigationOptions: () => ({
header: null,
headerMode: 'none',
headerTitle: null,
activeColor: '#f0edf6',
inactiveColor: '#3e2465',
barStyle: { backgroundColor: '#694fad' },
barStyle: {backgroundColor: '#694fad'},
/* headerLeft: (<HeaderBackButton />), */
drawerLabel: I18n.t('CREDIT_MANAGE'),
drawerIcon: ({ tintColor }) => (
<Icon
name={'credit-card'}
size={24}
/>)
}),
},
drawerIcon: ({tintColor}) => (
<Icon
name={'credit-card'}
size={24}
/>)
}),
},
historyItemDetails: HistoryItemDetails,
creditrequest: HistoryRequester,
addNetwork: AddNetwork,
updateinformation: UpdateInformations,
notificationview: Notifications,
configuration: Configurations,
about: About
})
historyItemDetails: HistoryItemDetails,
creditrequest: HistoryRequester,
addNetwork: AddNetwork,
updateinformation: UpdateInformations,
notificationview: Notifications,
configuration: Configurations,
about: About,
walletDetail: WalletDetail,
walletDepot: WalletDepot,
walletRetrait: WalletRetrait,
walletOptionSelect: WalletOptionSelect,
operateurOptionSelect: OperateurOptionSelect,
paiementFacture: PaiementFacture,
retraitEnCashAgent: RetraitEnCashAgent,
retraitCarteVersCashAgent: RetraitCarteVersCashAgent,
envoieCashVersWalletAgent: EnvoieCashVersWalletAgent,
envoieCashVersAutreWalletAgent: EnvoieCashVersAutreWalletAgent,
envoieCashVersCarteAgent: EnvoieCashVersCarteAgent,
envoiCashVersCashAgent: EnvoiCashVersCashAgent,
envoieWalletToBankAgent: EnvoieWalletToBankAgent,
createGroupNanoCredit: CreateGroupNanoCredit,
cautionNanoCreditAgent: CautionNanoCreditAgent,
})
}, {
contentComponent: OptionsMenu,
backBehavior: "none",
lazy: false,
headerMode: 'none', contentOptions: { activeTintColor: theme.accent }
})
contentComponent: OptionsMenu,
backBehavior: "none",
lazy: false,
headerMode: 'none', contentOptions: {activeTintColor: theme.accent}
});
const AppAdministratorStack = createDrawerNavigator({
sta: createStackNavigator({
home: Home,
useraccount: UserAccount,
Historique: {
screen: createBottomTabNavigator({
sta: createStackNavigator({
home: Home,
useraccount: UserAccount,
walletSelect: WalletSelect,
Historique: {
screen: createBottomTabNavigator({
myDemand: MyHistory, OthersDemand: MyHistory
}, {
}, {
headerMode: "none",
header: null,
headerTitle: null,
title: I18n.t('CREDIT_MANAGE'),
tabBarOptions: {
labelStyle: {
fontSize: 13,
},
labelStyle: {
fontSize: 13,
},
}
}),
navigationOptions: ({ navigation }) => ({
}),
navigationOptions: () => ({
header: null,
headerMode: 'none',
headerTitle: null,
activeColor: '#f0edf6',
inactiveColor: '#3e2465',
barStyle: { backgroundColor: '#694fad' },
barStyle: {backgroundColor: '#694fad'},
drawerLabel: I18n.t('CREDIT_MANAGE'),
drawerIcon: ({ tintColor }) => (
<Icon
name={'credit-card'}
size={24}
/>)
}),
},
creditrequest: HistoryRequester,
historyItemDetails: HistoryItemDetails,
drawerIcon: ({tintColor}) => (
<Icon
name={'credit-card'}
size={24}
/>)
}),
},
creditrequest: HistoryRequester,
historyItemDetails: HistoryItemDetails,
superviseurgroup: SuperViseurGroupeHome,
notificationview: Notifications,
configuration: Configurations,
about: About
superviseurgroup: SuperViseurGroupeHome,
notificationview: Notifications,
configuration: Configurations,
about: About,
walletDetail: WalletDetail,
walletDepot: WalletDepot,
walletRetrait: WalletRetrait
})
},
{
contentComponent: OptionsMenu,
backBehavior: "none",
headerMode: 'none'
});
})
},
{
contentComponent: OptionsMenu,
backBehavior: "none",
headerMode: 'none'
})
const AppSuperAdministrator = createDrawerNavigator({
sta: createStackNavigator({
home: Home,
useraccount: UserAccount,
Historique: {
screen: createBottomTabNavigator({ OthersDemand: MyHistory }, {
headerMode: "none",
header: null,
headerTitle: null,
title: I18n.t('CREDIT_MANAGE'),
tabBarOptions: {
labelStyle: {
fontSize: 13,
fontWeight: "bold"
},
}
}),
navigationOptions: ({ navigation }) => ({
title: I18n.t('CREDIT_MANAGE'),
headerMode: "none",
header: null,
headerTitle: null,
drawerIcon: ({ tintColor }) => (
<Icon
name={'credit-card'}
size={24}
/>)
}),
},
creditrequest: HistoryRequester,
historyItemDetails: HistoryItemDetails,
superviseurgroup: SuperViseurGroupeHome,
notificationview: Notifications,
configuration: Configurations,
about: About
sta: createStackNavigator({
home: Home,
useraccount: UserAccount,
walletSelect: WalletSelect,
Historique: {
screen: createBottomTabNavigator({OthersDemand: MyHistory}, {
headerMode: "none",
header: null,
headerTitle: null,
title: I18n.t('CREDIT_MANAGE'),
tabBarOptions: {
labelStyle: {
fontSize: 13,
fontWeight: "bold"
},
}
}),
navigationOptions: () => ({
title: I18n.t('CREDIT_MANAGE'),
headerMode: "none",
header: null,
headerTitle: null,
drawerIcon: ({tintColor}) => (
<Icon
name={'credit-card'}
size={24}
/>)
}),
},
creditrequest: HistoryRequester,
historyItemDetails: HistoryItemDetails,
superviseurgroup: SuperViseurGroupeHome,
notificationview: Notifications,
configuration: Configurations,
about: About,
walletDetail: WalletDetail,
walletDepot: WalletDepot,
walletRetrait: WalletRetrait
})
})
}, {
contentComponent: OptionsMenu,
backBehavior: "none",
headerMode: 'none'
})
contentComponent: OptionsMenu,
backBehavior: "none",
headerMode: 'none'
});
export const AppNavigator = createSwitchNavigator({
first: {
screen: SplashScreen
},
App: AppStack,
AgentApp: AppAgentStack,
adminApp: AppAdministratorStack,
supAdminApp: AppSuperAdministrator,
Auth: AuthStack
first: {
screen: SplashScreen
},
App: AppStack,
AgentApp: AppAgentStack,
adminApp: AppAdministratorStack,
supAdminApp: AppSuperAdministrator,
Auth: AuthStack
}, {
initialRouteName: 'first'
initialRouteName: 'first'
});
const AppContainer = createAppContainer(AppNavigator);
export default AppContainer;
class App extends React.Component {
constructor(props) {
super(props);
console.log("APP PROPS", this.props);
global.appHasLoaded = false;
IlinkEmitter.on("langueChange", this.updateLangue.bind(this))
//Remove this method to stop OneSignal Debugging
/* OneSignal.setLogLevel(6, 0);
// Replace 'YOUR_ONESIGNAL_APP_ID' with your OneSignal App ID.
OneSignal.init("e8e7251f-713d-4658-9510-86d877fa6a7c", {
kOSSettingsKeyAutoPrompt: false,
kOSSettingsKeyInAppLaunchURL: false,
kOSSettingsKeyInFocusDisplayOption: 2
});
OneSignal.inFocusDisplaying(2); // Controls what should happen if a notification is received while the app is open. 2 means that the notification will go directly to the device's notification center.
// The promptForPushNotifications function code will show the iOS push notification prompt. We recommend removing the following code and instead using an In-App Message to prompt for notification permission (See step below)
OneSignal.promptForPushNotificationsWithUserResponse(myiOSPromptCallback);
OneSignal.addEventListener('received', this.onReceived);
OneSignal.addEventListener('opened', this.onOpened);
OneSignal.addEventListener('ids', this.onIds);*/
}
updateLangue() {
this.forceUpdate()
}
_getOneSignalIds = () => {
return new Promise(async (resolve, reject) => {
try {
const getElement = await AsyncStorage.getItem('@config:onesignalIds');
resolve(getElement);
} catch (error) {
reject(error);
}
});
}
_saveOneSignalIds = async (ids) => {
try {
await AsyncStorage.setItem('@config:onesignalIds', ids);
} catch (error) {
console.warn(error);
}
}
goToScreen = (routeName, params, isReset = true) => {
const {navigator} = this.refs;
if (typeof navigator !== 'undefined') {
console.log("APP HAS LOADED", global.appHasLoaded);
if (global.appHasLoaded) {
navigator.dispatch({
type: "Navigation/NAVIGATE",
routeName,
params
});
/* readUser().then((result) => {
if (result === null || result === undefined) {
console.warn("APP HAS LOADED NOTIFICATION PARAMS", params);
navigator.dispatch({
type: "Navigation/NAVIGATE",
routeName: "first",
params: { routeName, params }
});
} else {
navigator.dispatch({
type: "Navigation/NAVIGATE",
routeName,
params
});
}
}); */
} else {
navigator.dispatch({
type: "Navigation/NAVIGATE",
routeName: "first",
params: {routeName, params}
});
}
}
};
handleDeepLink = (openResult) => {
const data = openResult.notification.payload.additionalData;
//const dataParse = data.replace("'", "\"");
console.warn("HANDLE DEEP LINK", data);
switch (data.screen) {
case 'historyItemDetails':
console.log("History Item");
this.goToScreen(data.screen, {
item: data.data
});
break;
default:
console.log("Not History Item");
this.goToScreen(data.screen, {
id: data.data.id
});
break;
}
/* if (data && data.id) {
this.goToScreen(data.screen, {
id: data.id,
goToScreen: this.goToScreen
});
} else {
console.log("notification is invalid data");
} */
};
componentWillUnmount() {
OneSignal.removeEventListener('received', this.onReceived);
OneSignal.removeEventListener('opened', this.onOpened);
OneSignal.removeEventListener('ids', this.onIds);
}
onReceived(notification) {
console.log("Notification received: ", notification);
}
onOpened = (openResult) => {
let data = openResult.notification.payload.additionalData;
this.handleDeepLink(openResult);
console.log('Message: ', openResult.notification.payload.body);
console.log('Data: ', openResult.notification.payload.additionalData);
console.log('isActive: ', openResult.notification.isAppInFocus);
console.log('openResult: ', openResult);
}
render() {
return (
<Provider store={store}>
<PersistGate persistor={persistor}>
<ActionSheetProvider>
<AppContainer ref="navigator"/>
</ActionSheetProvider>
</PersistGate>
</Provider>
);
}
}
function myiOSPromptCallback(permission) {
// do something with permission value
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});

View File

@ -182,6 +182,7 @@ android {
}
dependencies {
implementation project(':lottie-react-native')
implementation project(':react-native-onesignal')
implementation project(':react-native-maps')
implementation fileTree(dir: "libs", include: ["*.jar"])

View File

@ -5,7 +5,11 @@ import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
<<<<<<< Updated upstream:android/app/src/main/java/com/ilinktest/MainApplication.java
import com.geektime.rnonesignalandroid.ReactNativeOneSignalPackage;
=======
import com.airbnb.android.react.lottie.LottiePackage;
>>>>>>> Stashed changes:android/app/src/main/java/com/appli/ilink/MainApplication.java
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;

View File

@ -1,4 +1,6 @@
rootProject.name = 'iLink'
include ':lottie-react-native'
project(':lottie-react-native').projectDir = new File(rootProject.projectDir, '../node_modules/lottie-react-native/src/android')
include ':react-native-onesignal'
project(':react-native-onesignal').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-onesignal/android')
include ':react-native-maps'

View File

@ -1,4 +1,4 @@
{
"name": "iLinkWorld",
"name": "iLink",
"displayName": "iLinkWorld"
}
}

View File

@ -34,9 +34,16 @@ target 'iLink' do
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
pod 'react-native-geolocation', path: '../node_modules/@react-native-community/geolocation'
pod 'react-native-maps', :path => '../node_modules/react-native-maps'
<<<<<<< Updated upstream
pod 'react-native-onesignal', :path => '../node_modules/react-native-onesignal'
=======
# pod 'lottie-ios', :path => '../node_modules/lottie-ios'
pod 'lottie-react-native', :path => '../node_modules/lottie-react-native'
pod 'lottie-ios', '~> 3.1.3'
>>>>>>> Stashed changes
target 'iLinkTests' do
inherit! :search_paths

477
ios/Podfile.lock Normal file
View File

@ -0,0 +1,477 @@
PODS:
- boost-for-react-native (1.63.0)
- DoubleConversion (1.1.6)
- FBLazyVector (0.61.5)
- FBReactNativeSpec (0.61.5):
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.5)
- RCTTypeSafety (= 0.61.5)
- React-Core (= 0.61.5)
- React-jsi (= 0.61.5)
- ReactCommon/turbomodule/core (= 0.61.5)
- Folly (2018.10.22.00):
- boost-for-react-native
- DoubleConversion
- Folly/Default (= 2018.10.22.00)
- glog
- Folly/Default (2018.10.22.00):
- boost-for-react-native
- DoubleConversion
- glog
- GCDWebServer (3.5.4):
- GCDWebServer/Core (= 3.5.4)
- GCDWebServer/Core (3.5.4)
- glog (0.3.5)
- lottie-ios (3.1.9)
- lottie-react-native (3.3.2):
- lottie-ios (~> 3.1.3)
- React
- OneSignal (2.16.1)
- RCTRequired (0.61.5)
- RCTTypeSafety (0.61.5):
- FBLazyVector (= 0.61.5)
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.5)
- React-Core (= 0.61.5)
- React (0.61.5):
- React-Core (= 0.61.5)
- React-Core/DevSupport (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-RCTActionSheet (= 0.61.5)
- React-RCTAnimation (= 0.61.5)
- React-RCTBlob (= 0.61.5)
- React-RCTImage (= 0.61.5)
- React-RCTLinking (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTSettings (= 0.61.5)
- React-RCTText (= 0.61.5)
- React-RCTVibration (= 0.61.5)
- React-Core (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/CoreModulesHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/Default (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/DevSupport (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-jsinspector (= 0.61.5)
- Yoga
- React-Core/RCTActionSheetHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTAnimationHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTBlobHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTImageHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTLinkingHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTNetworkHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTSettingsHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTTextHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTVibrationHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTWebSocket (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-CoreModules (0.61.5):
- FBReactNativeSpec (= 0.61.5)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.61.5)
- React-Core/CoreModulesHeaders (= 0.61.5)
- React-RCTImage (= 0.61.5)
- ReactCommon/turbomodule/core (= 0.61.5)
- React-cxxreact (0.61.5):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsinspector (= 0.61.5)
- React-jsi (0.61.5):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsi/Default (= 0.61.5)
- React-jsi/Default (0.61.5):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsiexecutor (0.61.5):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsinspector (0.61.5)
- react-native-camera (3.40.0):
- React-Core
- react-native-camera/RCT (= 3.40.0)
- react-native-camera/RN (= 3.40.0)
- react-native-camera/RCT (3.40.0):
- React-Core
- react-native-camera/RN (3.40.0):
- React-Core
- react-native-geolocation (1.4.2):
- React
- react-native-maps (0.26.1):
- React
- react-native-onesignal (3.9.3):
- OneSignal (= 2.16.1)
- React (< 1.0.0, >= 0.13.0)
- react-native-viewpager (3.3.0):
- React
- React-RCTActionSheet (0.61.5):
- React-Core/RCTActionSheetHeaders (= 0.61.5)
- React-RCTAnimation (0.61.5):
- React-Core/RCTAnimationHeaders (= 0.61.5)
- React-RCTBlob (0.61.5):
- React-Core/RCTBlobHeaders (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-jsi (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTImage (0.61.5):
- React-Core/RCTImageHeaders (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTLinking (0.61.5):
- React-Core/RCTLinkingHeaders (= 0.61.5)
- React-RCTNetwork (0.61.5):
- React-Core/RCTNetworkHeaders (= 0.61.5)
- React-RCTSettings (0.61.5):
- React-Core/RCTSettingsHeaders (= 0.61.5)
- React-RCTText (0.61.5):
- React-Core/RCTTextHeaders (= 0.61.5)
- React-RCTVibration (0.61.5):
- React-Core/RCTVibrationHeaders (= 0.61.5)
- ReactCommon/jscallinvoker (0.61.5):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.5)
- ReactCommon/turbomodule/core (0.61.5):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- ReactCommon/jscallinvoker (= 0.61.5)
- RealmJS (3.6.5):
- GCDWebServer
- React
- RNCAsyncStorage (1.9.0):
- React
- RNDateTimePicker (2.4.0):
- React
- RNDeviceInfo (2.3.2):
- React
- RNGestureHandler (1.6.1):
- React
- RNI18n (2.0.15):
- React
- RNImageCropPicker (0.32.3):
- React-Core
- React-RCTImage
- RNImageCropPicker/QBImagePickerController (= 0.32.3)
- TOCropViewController
- RNImageCropPicker/QBImagePickerController (0.32.3):
- React-Core
- React-RCTImage
- TOCropViewController
- RNReanimated (1.13.2):
- React-Core
- RNScreens (2.3.0):
- React
- RNSVG (9.13.6):
- React
- RNVectorIcons (6.6.0):
- React
- SajjadBlurOverlay (1.0.0):
- React
- TOCropViewController (2.6.0)
- Yoga (1.14.0)
DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- lottie-ios (~> 3.1.3)
- lottie-react-native (from `../node_modules/lottie-react-native`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
- React (from `../node_modules/react-native/`)
- React-Core (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-camera (from `../node_modules/react-native-camera`)
- "react-native-geolocation (from `../node_modules/@react-native-community/geolocation`)"
- react-native-maps (from `../node_modules/react-native-maps`)
- react-native-onesignal (from `../node_modules/react-native-onesignal`)
- "react-native-viewpager (from `../node_modules/@react-native-community/viewpager`)"
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
- React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
- React-RCTImage (from `../node_modules/react-native/Libraries/Image`)
- React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`)
- React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`)
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/jscallinvoker (from `../node_modules/react-native/ReactCommon`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- RealmJS (from `../node_modules/realm`)
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNI18n (from `../node_modules/react-native-i18n`)
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNSVG (from `../node_modules/react-native-svg`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- SajjadBlurOverlay (from `../node_modules/react-native-blur-overlay/ios`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
trunk:
- boost-for-react-native
- GCDWebServer
- lottie-ios
- OneSignal
- TOCropViewController
EXTERNAL SOURCES:
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
FBLazyVector:
:path: "../node_modules/react-native/Libraries/FBLazyVector"
FBReactNativeSpec:
:path: "../node_modules/react-native/Libraries/FBReactNativeSpec"
Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
glog:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
lottie-react-native:
:path: "../node_modules/lottie-react-native"
RCTRequired:
:path: "../node_modules/react-native/Libraries/RCTRequired"
RCTTypeSafety:
:path: "../node_modules/react-native/Libraries/TypeSafety"
React:
:path: "../node_modules/react-native/"
React-Core:
:path: "../node_modules/react-native/"
React-CoreModules:
:path: "../node_modules/react-native/React/CoreModules"
React-cxxreact:
:path: "../node_modules/react-native/ReactCommon/cxxreact"
React-jsi:
:path: "../node_modules/react-native/ReactCommon/jsi"
React-jsiexecutor:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
react-native-camera:
:path: "../node_modules/react-native-camera"
react-native-geolocation:
:path: "../node_modules/@react-native-community/geolocation"
react-native-maps:
:path: "../node_modules/react-native-maps"
react-native-onesignal:
:path: "../node_modules/react-native-onesignal"
react-native-viewpager:
:path: "../node_modules/@react-native-community/viewpager"
React-RCTActionSheet:
:path: "../node_modules/react-native/Libraries/ActionSheetIOS"
React-RCTAnimation:
:path: "../node_modules/react-native/Libraries/NativeAnimation"
React-RCTBlob:
:path: "../node_modules/react-native/Libraries/Blob"
React-RCTImage:
:path: "../node_modules/react-native/Libraries/Image"
React-RCTLinking:
:path: "../node_modules/react-native/Libraries/LinkingIOS"
React-RCTNetwork:
:path: "../node_modules/react-native/Libraries/Network"
React-RCTSettings:
:path: "../node_modules/react-native/Libraries/Settings"
React-RCTText:
:path: "../node_modules/react-native/Libraries/Text"
React-RCTVibration:
:path: "../node_modules/react-native/Libraries/Vibration"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RealmJS:
:path: "../node_modules/realm"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
RNDateTimePicker:
:path: "../node_modules/@react-native-community/datetimepicker"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNI18n:
:path: "../node_modules/react-native-i18n"
RNImageCropPicker:
:path: "../node_modules/react-native-image-crop-picker"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
RNScreens:
:path: "../node_modules/react-native-screens"
RNSVG:
:path: "../node_modules/react-native-svg"
RNVectorIcons:
:path: "../node_modules/react-native-vector-icons"
SajjadBlurOverlay:
:path: "../node_modules/react-native-blur-overlay/ios"
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f
FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
lottie-ios: 3a3758ef5a008e762faec9c9d50a39842f26d124
lottie-react-native: 2a1a82bb326ae51331a5520de0cf706733c6db69
OneSignal: 5f6514ec2b931306eb067acb124afbb2e49970af
RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
React-CoreModules: d04f8494c1a328b69ec11db9d1137d667f916dcb
React-cxxreact: d0f7bcafa196ae410e5300736b424455e7fb7ba7
React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
react-native-camera: 35854c4f764a4a6cf61c1c3525888b92f0fe4b31
react-native-geolocation: a7b94614afbd5fd8350e0233a2025c8228fc8041
react-native-maps: 6e499eee4eabf422ba8b6f94e993cc768bf35153
react-native-onesignal: f92b6fae16388422f1b5d73b2c31e7000f481ae8
react-native-viewpager: a7b438ca32c57b2614ece2a123e7fe116f743131
React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
React-RCTImage: 6b8e8df449eb7c814c99a92d6b52de6fe39dea4e
React-RCTLinking: 121bb231c7503cf9094f4d8461b96a130fabf4a5
React-RCTNetwork: fb353640aafcee84ca8b78957297bd395f065c9a
React-RCTSettings: 8db258ea2a5efee381fcf7a6d5044e2f8b68b640
React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
RealmJS: b103c28012b1abfe13396ac82e76b4f4d9d47c0d
RNCAsyncStorage: 453cd7c335ec9ba3b877e27d02238956b76f3268
RNDateTimePicker: c4285bfdd87430f1e575b81a4742b7586a09d53e
RNDeviceInfo: 17e34f6dd902f08d88cbe2c0b7a01be948d43641
RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
RNI18n: e2f7e76389fcc6e84f2c8733ea89b92502351fd8
RNImageCropPicker: 54e5ea3d0e298ed51e1441a2fa0a0e7c90ee256d
RNReanimated: e03f7425cb7a38dcf1b644d680d1bfc91c3337ad
RNScreens: 03bf608b92ac0acf323f47d8f5b63a8f829340c8
RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
SajjadBlurOverlay: 4366a3417954b7d4a8a70682e0c43959ff76a3cb
TOCropViewController: 3105367e808b7d3d886a74ff59bf4804e7d3ab38
Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
PODFILE CHECKSUM: 74bfdaaa49d8b2d45ed01b2e94622d7dce1bbe9c
COCOAPODS: 1.10.0

View File

@ -0,0 +1 @@
../../../../../node_modules/@react-native-community/geolocation/ios/RNCGeolocation.h

View File

@ -0,0 +1 @@
../../../../../node_modules/@react-native-community/geolocation/ios/RNCGeolocation.h

View File

@ -0,0 +1,21 @@
{
"name": "react-native-geolocation",
"version": "1.4.2",
"summary": "React Native Geolocation Module for iOS and Android",
"license": "MIT",
"authors": "React Native Community",
"homepage": "https://github.com/react-native-community/react-native-geolocation#README.md",
"platforms": {
"ios": "9.0"
},
"source": {
"git": "https://github.com/react-native-community/react-native-geolocation.git",
"tag": "1.4.2"
},
"source_files": "ios/**/*.{h,m}",
"dependencies": {
"React": [
]
}
}

477
ios/Pods/Manifest.lock generated Normal file
View File

@ -0,0 +1,477 @@
PODS:
- boost-for-react-native (1.63.0)
- DoubleConversion (1.1.6)
- FBLazyVector (0.61.5)
- FBReactNativeSpec (0.61.5):
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.5)
- RCTTypeSafety (= 0.61.5)
- React-Core (= 0.61.5)
- React-jsi (= 0.61.5)
- ReactCommon/turbomodule/core (= 0.61.5)
- Folly (2018.10.22.00):
- boost-for-react-native
- DoubleConversion
- Folly/Default (= 2018.10.22.00)
- glog
- Folly/Default (2018.10.22.00):
- boost-for-react-native
- DoubleConversion
- glog
- GCDWebServer (3.5.4):
- GCDWebServer/Core (= 3.5.4)
- GCDWebServer/Core (3.5.4)
- glog (0.3.5)
- lottie-ios (3.1.9)
- lottie-react-native (3.3.2):
- lottie-ios (~> 3.1.3)
- React
- OneSignal (2.16.1)
- RCTRequired (0.61.5)
- RCTTypeSafety (0.61.5):
- FBLazyVector (= 0.61.5)
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.5)
- React-Core (= 0.61.5)
- React (0.61.5):
- React-Core (= 0.61.5)
- React-Core/DevSupport (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-RCTActionSheet (= 0.61.5)
- React-RCTAnimation (= 0.61.5)
- React-RCTBlob (= 0.61.5)
- React-RCTImage (= 0.61.5)
- React-RCTLinking (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTSettings (= 0.61.5)
- React-RCTText (= 0.61.5)
- React-RCTVibration (= 0.61.5)
- React-Core (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/CoreModulesHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/Default (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/DevSupport (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-jsinspector (= 0.61.5)
- Yoga
- React-Core/RCTActionSheetHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTAnimationHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTBlobHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTImageHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTLinkingHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTNetworkHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTSettingsHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTTextHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTVibrationHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-Core/RCTWebSocket (0.61.5):
- Folly (= 2018.10.22.00)
- glog
- React-Core/Default (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- Yoga
- React-CoreModules (0.61.5):
- FBReactNativeSpec (= 0.61.5)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.61.5)
- React-Core/CoreModulesHeaders (= 0.61.5)
- React-RCTImage (= 0.61.5)
- ReactCommon/turbomodule/core (= 0.61.5)
- React-cxxreact (0.61.5):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsinspector (= 0.61.5)
- React-jsi (0.61.5):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsi/Default (= 0.61.5)
- React-jsi/Default (0.61.5):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-jsiexecutor (0.61.5):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsinspector (0.61.5)
- react-native-camera (3.40.0):
- React-Core
- react-native-camera/RCT (= 3.40.0)
- react-native-camera/RN (= 3.40.0)
- react-native-camera/RCT (3.40.0):
- React-Core
- react-native-camera/RN (3.40.0):
- React-Core
- react-native-geolocation (1.4.2):
- React
- react-native-maps (0.26.1):
- React
- react-native-onesignal (3.9.3):
- OneSignal (= 2.16.1)
- React (< 1.0.0, >= 0.13.0)
- react-native-viewpager (3.3.0):
- React
- React-RCTActionSheet (0.61.5):
- React-Core/RCTActionSheetHeaders (= 0.61.5)
- React-RCTAnimation (0.61.5):
- React-Core/RCTAnimationHeaders (= 0.61.5)
- React-RCTBlob (0.61.5):
- React-Core/RCTBlobHeaders (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-jsi (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTImage (0.61.5):
- React-Core/RCTImageHeaders (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTLinking (0.61.5):
- React-Core/RCTLinkingHeaders (= 0.61.5)
- React-RCTNetwork (0.61.5):
- React-Core/RCTNetworkHeaders (= 0.61.5)
- React-RCTSettings (0.61.5):
- React-Core/RCTSettingsHeaders (= 0.61.5)
- React-RCTText (0.61.5):
- React-Core/RCTTextHeaders (= 0.61.5)
- React-RCTVibration (0.61.5):
- React-Core/RCTVibrationHeaders (= 0.61.5)
- ReactCommon/jscallinvoker (0.61.5):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-cxxreact (= 0.61.5)
- ReactCommon/turbomodule/core (0.61.5):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- ReactCommon/jscallinvoker (= 0.61.5)
- RealmJS (3.6.5):
- GCDWebServer
- React
- RNCAsyncStorage (1.9.0):
- React
- RNDateTimePicker (2.4.0):
- React
- RNDeviceInfo (2.3.2):
- React
- RNGestureHandler (1.6.1):
- React
- RNI18n (2.0.15):
- React
- RNImageCropPicker (0.32.3):
- React-Core
- React-RCTImage
- RNImageCropPicker/QBImagePickerController (= 0.32.3)
- TOCropViewController
- RNImageCropPicker/QBImagePickerController (0.32.3):
- React-Core
- React-RCTImage
- TOCropViewController
- RNReanimated (1.13.2):
- React-Core
- RNScreens (2.3.0):
- React
- RNSVG (9.13.6):
- React
- RNVectorIcons (6.6.0):
- React
- SajjadBlurOverlay (1.0.0):
- React
- TOCropViewController (2.6.0)
- Yoga (1.14.0)
DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- lottie-ios (~> 3.1.3)
- lottie-react-native (from `../node_modules/lottie-react-native`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
- React (from `../node_modules/react-native/`)
- React-Core (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-camera (from `../node_modules/react-native-camera`)
- "react-native-geolocation (from `../node_modules/@react-native-community/geolocation`)"
- react-native-maps (from `../node_modules/react-native-maps`)
- react-native-onesignal (from `../node_modules/react-native-onesignal`)
- "react-native-viewpager (from `../node_modules/@react-native-community/viewpager`)"
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
- React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
- React-RCTImage (from `../node_modules/react-native/Libraries/Image`)
- React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`)
- React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`)
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/jscallinvoker (from `../node_modules/react-native/ReactCommon`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- RealmJS (from `../node_modules/realm`)
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNI18n (from `../node_modules/react-native-i18n`)
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNSVG (from `../node_modules/react-native-svg`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- SajjadBlurOverlay (from `../node_modules/react-native-blur-overlay/ios`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
trunk:
- boost-for-react-native
- GCDWebServer
- lottie-ios
- OneSignal
- TOCropViewController
EXTERNAL SOURCES:
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
FBLazyVector:
:path: "../node_modules/react-native/Libraries/FBLazyVector"
FBReactNativeSpec:
:path: "../node_modules/react-native/Libraries/FBReactNativeSpec"
Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
glog:
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
lottie-react-native:
:path: "../node_modules/lottie-react-native"
RCTRequired:
:path: "../node_modules/react-native/Libraries/RCTRequired"
RCTTypeSafety:
:path: "../node_modules/react-native/Libraries/TypeSafety"
React:
:path: "../node_modules/react-native/"
React-Core:
:path: "../node_modules/react-native/"
React-CoreModules:
:path: "../node_modules/react-native/React/CoreModules"
React-cxxreact:
:path: "../node_modules/react-native/ReactCommon/cxxreact"
React-jsi:
:path: "../node_modules/react-native/ReactCommon/jsi"
React-jsiexecutor:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
react-native-camera:
:path: "../node_modules/react-native-camera"
react-native-geolocation:
:path: "../node_modules/@react-native-community/geolocation"
react-native-maps:
:path: "../node_modules/react-native-maps"
react-native-onesignal:
:path: "../node_modules/react-native-onesignal"
react-native-viewpager:
:path: "../node_modules/@react-native-community/viewpager"
React-RCTActionSheet:
:path: "../node_modules/react-native/Libraries/ActionSheetIOS"
React-RCTAnimation:
:path: "../node_modules/react-native/Libraries/NativeAnimation"
React-RCTBlob:
:path: "../node_modules/react-native/Libraries/Blob"
React-RCTImage:
:path: "../node_modules/react-native/Libraries/Image"
React-RCTLinking:
:path: "../node_modules/react-native/Libraries/LinkingIOS"
React-RCTNetwork:
:path: "../node_modules/react-native/Libraries/Network"
React-RCTSettings:
:path: "../node_modules/react-native/Libraries/Settings"
React-RCTText:
:path: "../node_modules/react-native/Libraries/Text"
React-RCTVibration:
:path: "../node_modules/react-native/Libraries/Vibration"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RealmJS:
:path: "../node_modules/realm"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
RNDateTimePicker:
:path: "../node_modules/@react-native-community/datetimepicker"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNI18n:
:path: "../node_modules/react-native-i18n"
RNImageCropPicker:
:path: "../node_modules/react-native-image-crop-picker"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
RNScreens:
:path: "../node_modules/react-native-screens"
RNSVG:
:path: "../node_modules/react-native-svg"
RNVectorIcons:
:path: "../node_modules/react-native-vector-icons"
SajjadBlurOverlay:
:path: "../node_modules/react-native-blur-overlay/ios"
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f
FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
lottie-ios: 3a3758ef5a008e762faec9c9d50a39842f26d124
lottie-react-native: 2a1a82bb326ae51331a5520de0cf706733c6db69
OneSignal: 5f6514ec2b931306eb067acb124afbb2e49970af
RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
React-CoreModules: d04f8494c1a328b69ec11db9d1137d667f916dcb
React-cxxreact: d0f7bcafa196ae410e5300736b424455e7fb7ba7
React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
react-native-camera: 35854c4f764a4a6cf61c1c3525888b92f0fe4b31
react-native-geolocation: a7b94614afbd5fd8350e0233a2025c8228fc8041
react-native-maps: 6e499eee4eabf422ba8b6f94e993cc768bf35153
react-native-onesignal: f92b6fae16388422f1b5d73b2c31e7000f481ae8
react-native-viewpager: a7b438ca32c57b2614ece2a123e7fe116f743131
React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
React-RCTImage: 6b8e8df449eb7c814c99a92d6b52de6fe39dea4e
React-RCTLinking: 121bb231c7503cf9094f4d8461b96a130fabf4a5
React-RCTNetwork: fb353640aafcee84ca8b78957297bd395f065c9a
React-RCTSettings: 8db258ea2a5efee381fcf7a6d5044e2f8b68b640
React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
RealmJS: b103c28012b1abfe13396ac82e76b4f4d9d47c0d
RNCAsyncStorage: 453cd7c335ec9ba3b877e27d02238956b76f3268
RNDateTimePicker: c4285bfdd87430f1e575b81a4742b7586a09d53e
RNDeviceInfo: 17e34f6dd902f08d88cbe2c0b7a01be948d43641
RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
RNI18n: e2f7e76389fcc6e84f2c8733ea89b92502351fd8
RNImageCropPicker: 54e5ea3d0e298ed51e1441a2fa0a0e7c90ee256d
RNReanimated: e03f7425cb7a38dcf1b644d680d1bfc91c3337ad
RNScreens: 03bf608b92ac0acf323f47d8f5b63a8f829340c8
RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
SajjadBlurOverlay: 4366a3417954b7d4a8a70682e0c43959ff76a3cb
TOCropViewController: 3105367e808b7d3d886a74ff59bf4804e7d3ab38
Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
PODFILE CHECKSUM: 74bfdaaa49d8b2d45ed01b2e94622d7dce1bbe9c
COCOAPODS: 1.10.0

14819
ios/Pods/Pods.xcodeproj/project.pbxproj generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GCDWebServer" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNCAsyncStorage" "${PODS_ROOT}/Headers/Public/RNDateTimePicker" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNI18n" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/RNSVG" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RNVectorIcons" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/SajjadBlurOverlay" "${PODS_ROOT}/Headers/Public/TOCropViewController" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/lottie-react-native" "${PODS_ROOT}/Headers/Public/react-native-camera" "${PODS_ROOT}/Headers/Public/react-native-geolocation" "${PODS_ROOT}/Headers/Public/react-native-maps" "${PODS_ROOT}/Headers/Public/react-native-onesignal" "${PODS_ROOT}/Headers/Public/react-native-viewpager"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,9 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GCDWebServer" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNCAsyncStorage" "${PODS_ROOT}/Headers/Public/RNDateTimePicker" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNI18n" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/RNSVG" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RNVectorIcons" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/SajjadBlurOverlay" "${PODS_ROOT}/Headers/Public/TOCropViewController" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/lottie-react-native" "${PODS_ROOT}/Headers/Public/react-native-camera" "${PODS_ROOT}/Headers/Public/react-native-geolocation" "${PODS_ROOT}/Headers/Public/react-native-maps" "${PODS_ROOT}/Headers/Public/react-native-onesignal" "${PODS_ROOT}/Headers/Public/react-native-viewpager"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,9 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GCDWebServer" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNCAsyncStorage" "${PODS_ROOT}/Headers/Public/RNDateTimePicker" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNI18n" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/RNSVG" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RNVectorIcons" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/SajjadBlurOverlay" "${PODS_ROOT}/Headers/Public/TOCropViewController" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/lottie-react-native" "${PODS_ROOT}/Headers/Public/react-native-camera" "${PODS_ROOT}/Headers/Public/react-native-geolocation" "${PODS_ROOT}/Headers/Public/react-native-maps" "${PODS_ROOT}/Headers/Public/react-native-onesignal" "${PODS_ROOT}/Headers/Public/react-native-viewpager"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,9 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GCDWebServer" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNCAsyncStorage" "${PODS_ROOT}/Headers/Public/RNDateTimePicker" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNI18n" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/RNSVG" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RNVectorIcons" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/SajjadBlurOverlay" "${PODS_ROOT}/Headers/Public/TOCropViewController" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/lottie-react-native" "${PODS_ROOT}/Headers/Public/react-native-camera" "${PODS_ROOT}/Headers/Public/react-native-geolocation" "${PODS_ROOT}/Headers/Public/react-native-maps" "${PODS_ROOT}/Headers/Public/react-native-onesignal" "${PODS_ROOT}/Headers/Public/react-native-viewpager"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,16 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/OneSignal/iOS_SDK/OneSignalSDK/Framework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GCDWebServer" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNCAsyncStorage" "${PODS_ROOT}/Headers/Public/RNDateTimePicker" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNI18n" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/RNSVG" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RNVectorIcons" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/SajjadBlurOverlay" "${PODS_ROOT}/Headers/Public/TOCropViewController" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/lottie-react-native" "${PODS_ROOT}/Headers/Public/react-native-camera" "${PODS_ROOT}/Headers/Public/react-native-geolocation" "${PODS_ROOT}/Headers/Public/react-native-maps" "${PODS_ROOT}/Headers/Public/react-native-onesignal" "${PODS_ROOT}/Headers/Public/react-native-viewpager" "$(PODS_ROOT)/Headers/Private/React-Core"
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/FBReactNativeSpec" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GCDWebServer" "${PODS_CONFIGURATION_BUILD_DIR}/RCTTypeSafety" "${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage" "${PODS_CONFIGURATION_BUILD_DIR}/RNDateTimePicker" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler" "${PODS_CONFIGURATION_BUILD_DIR}/RNI18n" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RNReanimated" "${PODS_CONFIGURATION_BUILD_DIR}/RNSVG" "${PODS_CONFIGURATION_BUILD_DIR}/RNScreens" "${PODS_CONFIGURATION_BUILD_DIR}/RNVectorIcons" "${PODS_CONFIGURATION_BUILD_DIR}/React-Core" "${PODS_CONFIGURATION_BUILD_DIR}/React-CoreModules" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTActionSheet" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration" "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsi" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector" "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon" "${PODS_CONFIGURATION_BUILD_DIR}/RealmJS" "${PODS_CONFIGURATION_BUILD_DIR}/SajjadBlurOverlay" "${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController" "${PODS_CONFIGURATION_BUILD_DIR}/Yoga" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-camera" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-geolocation" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-maps" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-onesignal" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-viewpager" "${PODS_ROOT}/../../node_modules/realm/vendor/realm-ios"
OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.modulemap" -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native/lottie_react_native.modulemap"
OTHER_LDFLAGS = $(inherited) -ObjC -l"DoubleConversion" -l"FBReactNativeSpec" -l"Folly" -l"GCDWebServer" -l"RCTTypeSafety" -l"RNCAsyncStorage" -l"RNDateTimePicker" -l"RNDeviceInfo" -l"RNGestureHandler" -l"RNI18n" -l"RNImageCropPicker" -l"RNReanimated" -l"RNSVG" -l"RNScreens" -l"RNVectorIcons" -l"React-Core" -l"React-CoreModules" -l"React-RCTActionSheet" -l"React-RCTAnimation" -l"React-RCTBlob" -l"React-RCTImage" -l"React-RCTLinking" -l"React-RCTNetwork" -l"React-RCTSettings" -l"React-RCTText" -l"React-RCTVibration" -l"React-cxxreact" -l"React-jsi" -l"React-jsiexecutor" -l"React-jsinspector" -l"ReactCommon" -l"RealmJS" -l"SajjadBlurOverlay" -l"TOCropViewController" -l"Yoga" -l"c++" -l"glog" -l"lottie-ios" -l"lottie-react-native" -l"react-native-camera" -l"react-native-geolocation" -l"react-native-maps" -l"react-native-onesignal" -l"react-native-viewpager" -l"realm-ios" -l"realm-parser-ios" -l"stdc++" -l"z" -framework "CFNetwork" -framework "CoreGraphics" -framework "JavaScriptCore" -framework "MobileCoreServices" -framework "OneSignal" -framework "Photos" -framework "QuartzCore" -framework "SystemConfiguration" -framework "UIKit" -framework "UserNotifications" -framework "WebKit"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.modulemap" -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native/lottie_react_native.modulemap"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native"
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,16 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/OneSignal/iOS_SDK/OneSignalSDK/Framework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GCDWebServer" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNCAsyncStorage" "${PODS_ROOT}/Headers/Public/RNDateTimePicker" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNI18n" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/RNSVG" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RNVectorIcons" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/SajjadBlurOverlay" "${PODS_ROOT}/Headers/Public/TOCropViewController" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/lottie-react-native" "${PODS_ROOT}/Headers/Public/react-native-camera" "${PODS_ROOT}/Headers/Public/react-native-geolocation" "${PODS_ROOT}/Headers/Public/react-native-maps" "${PODS_ROOT}/Headers/Public/react-native-onesignal" "${PODS_ROOT}/Headers/Public/react-native-viewpager" "$(PODS_ROOT)/Headers/Private/React-Core"
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/DoubleConversion" "${PODS_CONFIGURATION_BUILD_DIR}/FBReactNativeSpec" "${PODS_CONFIGURATION_BUILD_DIR}/Folly" "${PODS_CONFIGURATION_BUILD_DIR}/GCDWebServer" "${PODS_CONFIGURATION_BUILD_DIR}/RCTTypeSafety" "${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage" "${PODS_CONFIGURATION_BUILD_DIR}/RNDateTimePicker" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNGestureHandler" "${PODS_CONFIGURATION_BUILD_DIR}/RNI18n" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RNReanimated" "${PODS_CONFIGURATION_BUILD_DIR}/RNSVG" "${PODS_CONFIGURATION_BUILD_DIR}/RNScreens" "${PODS_CONFIGURATION_BUILD_DIR}/RNVectorIcons" "${PODS_CONFIGURATION_BUILD_DIR}/React-Core" "${PODS_CONFIGURATION_BUILD_DIR}/React-CoreModules" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTActionSheet" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTAnimation" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTBlob" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTImage" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTLinking" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTSettings" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTText" "${PODS_CONFIGURATION_BUILD_DIR}/React-RCTVibration" "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsi" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsiexecutor" "${PODS_CONFIGURATION_BUILD_DIR}/React-jsinspector" "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon" "${PODS_CONFIGURATION_BUILD_DIR}/RealmJS" "${PODS_CONFIGURATION_BUILD_DIR}/SajjadBlurOverlay" "${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController" "${PODS_CONFIGURATION_BUILD_DIR}/Yoga" "${PODS_CONFIGURATION_BUILD_DIR}/glog" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-camera" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-geolocation" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-maps" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-onesignal" "${PODS_CONFIGURATION_BUILD_DIR}/react-native-viewpager" "${PODS_ROOT}/../../node_modules/realm/vendor/realm-ios"
OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.modulemap" -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native/lottie_react_native.modulemap"
OTHER_LDFLAGS = $(inherited) -ObjC -l"DoubleConversion" -l"FBReactNativeSpec" -l"Folly" -l"GCDWebServer" -l"RCTTypeSafety" -l"RNCAsyncStorage" -l"RNDateTimePicker" -l"RNDeviceInfo" -l"RNGestureHandler" -l"RNI18n" -l"RNImageCropPicker" -l"RNReanimated" -l"RNSVG" -l"RNScreens" -l"RNVectorIcons" -l"React-Core" -l"React-CoreModules" -l"React-RCTActionSheet" -l"React-RCTAnimation" -l"React-RCTBlob" -l"React-RCTImage" -l"React-RCTLinking" -l"React-RCTNetwork" -l"React-RCTSettings" -l"React-RCTText" -l"React-RCTVibration" -l"React-cxxreact" -l"React-jsi" -l"React-jsiexecutor" -l"React-jsinspector" -l"ReactCommon" -l"RealmJS" -l"SajjadBlurOverlay" -l"TOCropViewController" -l"Yoga" -l"c++" -l"glog" -l"lottie-ios" -l"lottie-react-native" -l"react-native-camera" -l"react-native-geolocation" -l"react-native-maps" -l"react-native-onesignal" -l"react-native-viewpager" -l"realm-ios" -l"realm-parser-ios" -l"stdc++" -l"z" -framework "CFNetwork" -framework "CoreGraphics" -framework "JavaScriptCore" -framework "MobileCoreServices" -framework "OneSignal" -framework "Photos" -framework "QuartzCore" -framework "SystemConfiguration" -framework "UIKit" -framework "UserNotifications" -framework "WebKit"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.modulemap" -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native/lottie_react_native.modulemap"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native"
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,14 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/OneSignal/iOS_SDK/OneSignalSDK/Framework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GCDWebServer" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNCAsyncStorage" "${PODS_ROOT}/Headers/Public/RNDateTimePicker" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNI18n" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/RNSVG" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RNVectorIcons" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/SajjadBlurOverlay" "${PODS_ROOT}/Headers/Public/TOCropViewController" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/lottie-react-native" "${PODS_ROOT}/Headers/Public/react-native-camera" "${PODS_ROOT}/Headers/Public/react-native-geolocation" "${PODS_ROOT}/Headers/Public/react-native-maps" "${PODS_ROOT}/Headers/Public/react-native-onesignal" "${PODS_ROOT}/Headers/Public/react-native-viewpager" "$(PODS_ROOT)/Headers/Private/React-Core"
OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.modulemap" -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native/lottie_react_native.modulemap"
OTHER_LDFLAGS = $(inherited) -l"c++" -l"stdc++" -l"z" -framework "CFNetwork" -framework "CoreGraphics" -framework "JavaScriptCore" -framework "MobileCoreServices" -framework "Photos" -framework "QuartzCore" -framework "SystemConfiguration" -framework "UIKit" -framework "UserNotifications" -framework "WebKit"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.modulemap" -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native/lottie_react_native.modulemap"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native"
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,14 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/OneSignal/iOS_SDK/OneSignalSDK/Framework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/FBLazyVector" "${PODS_ROOT}/Headers/Public/FBReactNativeSpec" "${PODS_ROOT}/Headers/Public/GCDWebServer" "${PODS_ROOT}/Headers/Public/RCTRequired" "${PODS_ROOT}/Headers/Public/RCTTypeSafety" "${PODS_ROOT}/Headers/Public/RNCAsyncStorage" "${PODS_ROOT}/Headers/Public/RNDateTimePicker" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNGestureHandler" "${PODS_ROOT}/Headers/Public/RNI18n" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RNReanimated" "${PODS_ROOT}/Headers/Public/RNSVG" "${PODS_ROOT}/Headers/Public/RNScreens" "${PODS_ROOT}/Headers/Public/RNVectorIcons" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/ReactCommon" "${PODS_ROOT}/Headers/Public/SajjadBlurOverlay" "${PODS_ROOT}/Headers/Public/TOCropViewController" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/lottie-react-native" "${PODS_ROOT}/Headers/Public/react-native-camera" "${PODS_ROOT}/Headers/Public/react-native-geolocation" "${PODS_ROOT}/Headers/Public/react-native-maps" "${PODS_ROOT}/Headers/Public/react-native-onesignal" "${PODS_ROOT}/Headers/Public/react-native-viewpager" "$(PODS_ROOT)/Headers/Private/React-Core"
OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.modulemap" -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native/lottie_react_native.modulemap"
OTHER_LDFLAGS = $(inherited) -l"c++" -l"stdc++" -l"z" -framework "CFNetwork" -framework "CoreGraphics" -framework "JavaScriptCore" -framework "MobileCoreServices" -framework "Photos" -framework "QuartzCore" -framework "SystemConfiguration" -framework "UIKit" -framework "UserNotifications" -framework "WebKit"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.modulemap" -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native/lottie_react_native.modulemap"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
PODS_ROOT = ${SRCROOT}/Pods
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-react-native"
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,12 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../node_modules/lottie-ios
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,12 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/lottie-ios
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_react_native_geolocation : NSObject
@end
@implementation PodsDummy_react_native_geolocation
@end

View File

@ -0,0 +1,12 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif

View File

@ -0,0 +1,12 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/react-native-geolocation
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/react-native-geolocation" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-geolocation"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../node_modules/@react-native-community/geolocation
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,12 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/react-native-geolocation
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/react-native-geolocation" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/DoubleConversion" "${PODS_ROOT}/Headers/Public/React-Core" "${PODS_ROOT}/Headers/Public/React-RCTBlob" "${PODS_ROOT}/Headers/Public/React-RCTText" "${PODS_ROOT}/Headers/Public/React-cxxreact" "${PODS_ROOT}/Headers/Public/React-jsi" "${PODS_ROOT}/Headers/Public/React-jsiexecutor" "${PODS_ROOT}/Headers/Public/React-jsinspector" "${PODS_ROOT}/Headers/Public/Yoga" "${PODS_ROOT}/Headers/Public/glog" "${PODS_ROOT}/Headers/Public/react-native-geolocation"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../node_modules/@react-native-community/geolocation
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

201
ios/Pods/lottie-ios/LICENSE generated Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2018 Airbnb, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

110
ios/Pods/lottie-ios/README.md generated Normal file
View File

@ -0,0 +1,110 @@
# Lottie for iOS, macOS (and [Android](https://github.com/airbnb/lottie-android) and [React Native](https://github.com/airbnb/lottie-react-native))
[![Version](https://img.shields.io/cocoapods/v/lottie-ios.svg?style=flat)](https://cocoapods.org/pods/lottie-ios)[![License](https://img.shields.io/cocoapods/l/lottie-ios.svg?style=flat)](https://cocoapods.org/pods/lottie-ios)[![Platform](https://img.shields.io/cocoapods/p/lottie-ios.svg?style=flat)](https://cocoapods.org/pods/lottie-ios)
# View documentation, FAQ, help, examples, and more at [airbnb.io/lottie](http://airbnb.io/lottie/)
Lottie is a mobile library for Android and iOS that natively renders vector based animations and art in realtime with minimal code.
Lottie loads and renders animations and vectors exported in the bodymovin JSON format. Bodymovin JSON can be created and exported from After Effects with [bodymovin](https://github.com/bodymovin/bodymovin), Sketch with [Lottie Sketch Export](https://github.com/buba447/Lottie-Sketch-Export), and from [Haiku](https://www.haiku.ai).
For the first time, designers can create **and ship** beautiful animations without an engineer painstakingly recreating it by hand.
Since the animation is backed by JSON they are extremely small in size but can be large in complexity!
Animations can be played, resized, looped, sped up, slowed down, reversed, and even interactively scrubbed.
Lottie can play or loop just a portion of the animation as well, the possibilities are endless!
Animations can even be ***changed at runtime*** in various ways! Change the color, position or any keyframable value!
Lottie also supports native UIViewController Transitions out of the box!
Here is just a small sampling of the power of Lottie
![Example1](_Gifs/Examples1.gif)
![Example2](_Gifs/Examples2.gif)
<img src="_Gifs/Community 2_3.gif" />
![Example3](_Gifs/Examples3.gif)
![Abcs](_Gifs/Examples4.gif)
## Installing Lottie
Lottie supports [CocoaPods](https://cocoapods.org/) and [Carthage](https://github.com/Carthage/Carthage) (Both dynamic and static). Lottie is written in ***Swift 4.2***.
### Github Repo
You can pull the [Lottie Github Repo](https://github.com/airbnb/lottie-ios/) and include the Lottie.xcodeproj to build a dynamic or static library.
### CocoaPods
Add the pod to your Podfile:
```ruby
pod 'lottie-ios'
```
And then run:
```ruby
pod install
```
After installing the cocoapod into your project import Lottie with
```swift
import Lottie
```
### Carthage
Add Lottie to your Cartfile:
```
github "airbnb/lottie-ios" "master"
```
And then run:
```
carthage update
```
In your application targets “General” tab under the “Linked Frameworks and Libraries” section, drag and drop lottie-ios.framework from the Carthage/Build/iOS directory that `carthage update` produced.
### Swift Package Manager
``` swift
// swift-tools-version:5.1
import PackageDescription
let package = Package(
name: "YourTestProject",
platforms: [
.iOS(.v12),
],
dependencies: [
.package(url: "https://github.com/airbnb/lottie-ios.git", from: "3.1.2")
],
targets: [
.target(name: "YourTestProject", dependencies: ["Lottie"])
]
)
```
And then import wherever needed: ```import Lottie```
#### Adding it to an existent iOS Project via Swift Package Manager
1. Using Xcode 11 go to File > Swift Packages > Add Package Dependency
2. Paste the project URL: https://github.com/airbnb/lottie-ios
3. Click on next and select the project target
4. Don't forget to set `DEAD_CODE_STRIPPING = NO` in your `Build Settings` (https://bugs.swift.org/plugins/servlet/mobile#issue/SR-11564)
**NOTE: For MacOS you must set the `Branch` field to `lottie/macos-spm`
![Example](_Gifs/spm-branch.png)
If you have doubts, please, check the following links:
[How to use](https://developer.apple.com/videos/play/wwdc2019/408/)
[Creating Swift Packages](https://developer.apple.com/videos/play/wwdc2019/410/)
After successfully retrieved the package and added it to your project, just import `Lottie` and you can get the full benefits of it.
### Objective-C Support
As of 3.0 Lottie has been completely rewritten in Swift!
For Objective-C support please use Lottie 2.5.3. Alternatively an Objective-C branch exists and is still active.
The official objective c branch can be found here:
[Objective-C Branch](https://github.com/airbnb/lottie-ios/tree/lottie/objectiveC)
Also check out the documentation regarding it here:
[iOS Migration](http://airbnb.io/lottie/#/ios-migration)

View File

@ -0,0 +1,209 @@
//
// AnimationContainer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/24/19.
//
import Foundation
import QuartzCore
/**
The base animation container.
This layer holds a single composition container and allows for animation of
the currentFrame property.
*/
final class AnimationContainer: CALayer {
/// The animatable Current Frame Property
@NSManaged var currentFrame: CGFloat
var imageProvider: AnimationImageProvider {
get {
return layerImageProvider.imageProvider
}
set {
layerImageProvider.imageProvider = newValue
}
}
func reloadImages() {
layerImageProvider.reloadImages()
}
var renderScale: CGFloat = 1 {
didSet {
animationLayers.forEach({ $0.renderScale = renderScale })
}
}
public var respectAnimationFrameRate: Bool = false
/// Forces the view to update its drawing.
func forceDisplayUpdate() {
animationLayers.forEach( { $0.displayWithFrame(frame: currentFrame, forceUpdates: true) })
}
func logHierarchyKeypaths() {
print("Lottie: Logging Animation Keypaths")
animationLayers.forEach({ $0.logKeypaths(for: nil) })
}
func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) {
for layer in animationLayers {
if let foundProperties = layer.nodeProperties(for: keypath) {
for property in foundProperties {
property.setProvider(provider: valueProvider)
}
layer.displayWithFrame(frame: presentation()?.currentFrame ?? currentFrame, forceUpdates: true)
}
}
}
func getValue(for keypath: AnimationKeypath, atFrame: CGFloat?) -> Any? {
for layer in animationLayers {
if let foundProperties = layer.nodeProperties(for: keypath),
let first = foundProperties.first {
return first.valueProvider.value(frame: atFrame ?? currentFrame)
}
}
return nil
}
func layer(for keypath: AnimationKeypath) -> CALayer? {
for layer in animationLayers {
if let foundLayer = layer.layer(for: keypath) {
return foundLayer
}
}
return nil
}
func animatorNodes(for keypath: AnimationKeypath) -> [AnimatorNode]? {
var results = [AnimatorNode]()
for layer in animationLayers {
if let nodes = layer.animatorNodes(for: keypath) {
results.append(contentsOf: nodes)
}
}
if results.count == 0 {
return nil
}
return results
}
var textProvider: AnimationTextProvider {
get { return layerTextProvider.textProvider }
set { layerTextProvider.textProvider = newValue }
}
var fontProvider: AnimationFontProvider {
get { return layerFontProvider.fontProvider }
set { layerFontProvider.fontProvider = newValue }
}
var animationLayers: ContiguousArray<CompositionLayer>
fileprivate let layerImageProvider: LayerImageProvider
fileprivate let layerTextProvider: LayerTextProvider
fileprivate let layerFontProvider: LayerFontProvider
init(animation: Animation, imageProvider: AnimationImageProvider, textProvider: AnimationTextProvider, fontProvider: AnimationFontProvider) {
self.layerImageProvider = LayerImageProvider(imageProvider: imageProvider, assets: animation.assetLibrary?.imageAssets)
self.layerTextProvider = LayerTextProvider(textProvider: textProvider)
self.layerFontProvider = LayerFontProvider(fontProvider: fontProvider)
self.animationLayers = []
super.init()
bounds = animation.bounds
let layers = animation.layers.initializeCompositionLayers(assetLibrary: animation.assetLibrary, layerImageProvider: layerImageProvider, textProvider: textProvider, fontProvider: fontProvider, frameRate: CGFloat(animation.framerate))
var imageLayers = [ImageCompositionLayer]()
var textLayers = [TextCompositionLayer]()
var mattedLayer: CompositionLayer? = nil
for layer in layers.reversed() {
layer.bounds = bounds
animationLayers.append(layer)
if let imageLayer = layer as? ImageCompositionLayer {
imageLayers.append(imageLayer)
}
if let textLayer = layer as? TextCompositionLayer {
textLayers.append(textLayer)
}
if let matte = mattedLayer {
/// The previous layer requires this layer to be its matte
matte.matteLayer = layer
mattedLayer = nil
continue
}
if let matte = layer.matteType,
(matte == .add || matte == .invert) {
/// We have a layer that requires a matte.
mattedLayer = layer
}
addSublayer(layer)
}
layerImageProvider.addImageLayers(imageLayers)
layerImageProvider.reloadImages()
layerTextProvider.addTextLayers(textLayers)
layerTextProvider.reloadTexts()
layerFontProvider.addTextLayers(textLayers)
layerFontProvider.reloadTexts()
setNeedsDisplay()
}
/// For CAAnimation Use
public override init(layer: Any) {
self.animationLayers = []
self.layerImageProvider = LayerImageProvider(imageProvider: BlankImageProvider(), assets: nil)
self.layerTextProvider = LayerTextProvider(textProvider: DefaultTextProvider())
self.layerFontProvider = LayerFontProvider(fontProvider: DefaultFontProvider())
super.init(layer: layer)
guard let animationLayer = layer as? AnimationContainer else { return }
currentFrame = animationLayer.currentFrame
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: CALayer Animations
override public class func needsDisplay(forKey key: String) -> Bool {
if key == "currentFrame" {
return true
}
return super.needsDisplay(forKey: key)
}
override public func action(forKey event: String) -> CAAction? {
if event == "currentFrame" {
let animation = CABasicAnimation(keyPath: event)
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
animation.fromValue = self.presentation()?.currentFrame
return animation
}
return super.action(forKey: event)
}
public override func display() {
guard Thread.isMainThread else { return }
var newFrame: CGFloat = self.presentation()?.currentFrame ?? self.currentFrame
if respectAnimationFrameRate {
newFrame = floor(newFrame)
}
animationLayers.forEach( { $0.displayWithFrame(frame: newFrame, forceUpdates: false) })
}
}
fileprivate class BlankImageProvider: AnimationImageProvider {
func imageForAsset(asset: ImageAsset) -> CGImage? {
return nil
}
}

View File

@ -0,0 +1,153 @@
//
// LayerContainer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/22/19.
//
import Foundation
import QuartzCore
/**
The base class for a child layer of CompositionContainer
*/
class CompositionLayer: CALayer, KeypathSearchable {
weak var layerDelegate: CompositionLayerDelegate?
let transformNode: LayerTransformNode
let contentsLayer: CALayer = CALayer()
let maskLayer: MaskContainerLayer?
let matteType: MatteType?
var renderScale: CGFloat = 1 {
didSet {
self.updateRenderScale()
}
}
var matteLayer: CompositionLayer? {
didSet {
if let matte = matteLayer {
if let type = matteType, type == .invert {
mask = InvertedMatteLayer(inputMatte: matte)
} else {
mask = matte
}
} else {
mask = nil
}
}
}
let inFrame: CGFloat
let outFrame: CGFloat
let startFrame: CGFloat
let timeStretch: CGFloat
init(layer: LayerModel, size: CGSize) {
self.transformNode = LayerTransformNode(transform: layer.transform)
if let masks = layer.masks {
maskLayer = MaskContainerLayer(masks: masks)
} else {
maskLayer = nil
}
self.matteType = layer.matte
self.inFrame = layer.inFrame.cgFloat
self.outFrame = layer.outFrame.cgFloat
self.timeStretch = layer.timeStretch.cgFloat
self.startFrame = layer.startTime.cgFloat
self.keypathName = layer.name
self.childKeypaths = [transformNode.transformProperties]
super.init()
self.anchorPoint = .zero
self.actions = [
"opacity" : NSNull(),
"transform" : NSNull(),
"bounds" : NSNull(),
"anchorPoint" : NSNull(),
"sublayerTransform" : NSNull()
]
contentsLayer.anchorPoint = .zero
contentsLayer.bounds = CGRect(origin: .zero, size: size)
contentsLayer.actions = [
"opacity" : NSNull(),
"transform" : NSNull(),
"bounds" : NSNull(),
"anchorPoint" : NSNull(),
"sublayerTransform" : NSNull(),
"hidden" : NSNull()
]
addSublayer(contentsLayer)
if let maskLayer = maskLayer {
contentsLayer.mask = maskLayer
}
}
override init(layer: Any) {
/// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
guard let layer = layer as? CompositionLayer else {
fatalError("Wrong Layer Class")
}
self.transformNode = layer.transformNode
self.matteType = layer.matteType
self.inFrame = layer.inFrame
self.outFrame = layer.outFrame
self.timeStretch = layer.timeStretch
self.startFrame = layer.startFrame
self.keypathName = layer.keypathName
self.childKeypaths = [transformNode.transformProperties]
self.maskLayer = nil
super.init(layer: layer)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
final func displayWithFrame(frame: CGFloat, forceUpdates: Bool) {
transformNode.updateTree(frame, forceUpdates: forceUpdates)
let layerVisible = frame.isInRangeOrEqual(inFrame, outFrame)
/// Only update contents if current time is within the layers time bounds.
if layerVisible {
displayContentsWithFrame(frame: frame, forceUpdates: forceUpdates)
maskLayer?.updateWithFrame(frame: frame, forceUpdates: forceUpdates)
}
contentsLayer.transform = transformNode.globalTransform
contentsLayer.opacity = transformNode.opacity
contentsLayer.isHidden = !layerVisible
layerDelegate?.frameUpdated(frame: frame)
}
func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
/// To be overridden by subclass
}
// MARK: Keypath Searchable
let keypathName: String
var keypathProperties: [String : AnyNodeProperty] {
return [:]
}
final var childKeypaths: [KeypathSearchable]
var keypathLayer: CALayer? {
return contentsLayer
}
func updateRenderScale() {
self.contentsScale = self.renderScale
}
}
protocol CompositionLayerDelegate: class {
func frameUpdated(frame: CGFloat)
}

View File

@ -0,0 +1,47 @@
//
// ImageCompositionLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/25/19.
//
import Foundation
import CoreGraphics
import QuartzCore
final class ImageCompositionLayer: CompositionLayer {
var image: CGImage? = nil {
didSet {
if let image = image {
contentsLayer.contents = image
} else {
contentsLayer.contents = nil
}
}
}
let imageReferenceID: String
init(imageLayer: ImageLayerModel, size: CGSize) {
self.imageReferenceID = imageLayer.referenceID
super.init(layer: imageLayer, size: size)
contentsLayer.masksToBounds = true
contentsLayer.contentsGravity = CALayerContentsGravity.resize
}
override init(layer: Any) {
/// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
guard let layer = layer as? ImageCompositionLayer else {
fatalError("init(layer:) Wrong Layer Class")
}
self.imageReferenceID = layer.imageReferenceID
self.image = nil
super.init(layer: layer)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@ -0,0 +1,168 @@
//
// MaskContainerLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/25/19.
//
import Foundation
import QuartzCore
extension MaskMode {
var usableMode: MaskMode {
switch self {
case .add:
return .add
case .subtract:
return .subtract
case .intersect:
return .intersect
case .lighten:
return .add
case .darken:
return .darken
case .difference:
return .intersect
case .none:
return .none
}
}
}
final class MaskContainerLayer: CALayer {
init(masks: [Mask]) {
super.init()
anchorPoint = .zero
var containerLayer = CALayer()
var firstObject: Bool = true
for mask in masks {
let maskLayer = MaskLayer(mask: mask)
maskLayers.append(maskLayer)
if mask.mode.usableMode == .none {
continue
} else if mask.mode.usableMode == .add || firstObject {
firstObject = false
containerLayer.addSublayer(maskLayer)
} else {
containerLayer.mask = maskLayer
let newContainer = CALayer()
newContainer.addSublayer(containerLayer)
containerLayer = newContainer
}
}
addSublayer(containerLayer)
}
override init(layer: Any) {
/// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
guard let layer = layer as? MaskContainerLayer else {
fatalError("init(layer:) Wrong Layer Class")
}
super.init(layer: layer)
}
fileprivate var maskLayers: [MaskLayer] = []
func updateWithFrame(frame: CGFloat, forceUpdates: Bool) {
maskLayers.forEach({ $0.updateWithFrame(frame: frame, forceUpdates: forceUpdates) })
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension CGRect {
static var veryLargeRect: CGRect {
return CGRect(x: -100_000_000,
y: -100_000_000,
width: 200_000_000,
height: 200_000_000)
}
}
fileprivate class MaskLayer: CALayer {
let properties: MaskNodeProperties?
let maskLayer = CAShapeLayer()
init(mask: Mask) {
self.properties = MaskNodeProperties(mask: mask)
super.init()
addSublayer(maskLayer)
anchorPoint = .zero
maskLayer.fillColor = mask.mode == .add ? CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1, 0, 0, 1]) :
CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [0, 1, 0, 1])
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
self.actions = [
"opacity" : NSNull()
]
}
override init(layer: Any) {
self.properties = nil
super.init(layer: layer)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func updateWithFrame(frame: CGFloat, forceUpdates: Bool) {
guard let properties = properties else { return }
if properties.opacity.needsUpdate(frame: frame) || forceUpdates {
properties.opacity.update(frame: frame)
self.opacity = Float(properties.opacity.value.cgFloatValue)
}
if properties.shape.needsUpdate(frame: frame) || forceUpdates {
properties.shape.update(frame: frame)
properties.expansion.update(frame: frame)
let shapePath = properties.shape.value.cgPath()
var path = shapePath
if properties.mode.usableMode == .subtract && !properties.inverted ||
(properties.mode.usableMode == .add && properties.inverted) {
/// Add a bounds rect to invert the mask
let newPath = CGMutablePath()
newPath.addRect(CGRect.veryLargeRect)
newPath.addPath(shapePath)
path = newPath
}
maskLayer.path = path
}
}
}
fileprivate class MaskNodeProperties: NodePropertyMap {
var propertyMap: [String : AnyNodeProperty]
var properties: [AnyNodeProperty]
init(mask: Mask) {
self.mode = mask.mode
self.inverted = mask.inverted
self.opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: mask.opacity.keyframes))
self.shape = NodeProperty(provider: KeyframeInterpolator(keyframes: mask.shape.keyframes))
self.expansion = NodeProperty(provider: KeyframeInterpolator(keyframes: mask.expansion.keyframes))
self.propertyMap = [
"Opacity" : opacity,
"Shape" : shape,
"Expansion" : expansion
]
self.properties = Array(self.propertyMap.values)
}
let mode: MaskMode
let inverted: Bool
let opacity: NodeProperty<Vector1D>
let shape: NodeProperty<BezierPath>
let expansion: NodeProperty<Vector1D>
}

View File

@ -0,0 +1,28 @@
//
// NullCompositionLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/25/19.
//
import Foundation
final class NullCompositionLayer: CompositionLayer {
init(layer: LayerModel) {
super.init(layer: layer, size: .zero)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(layer: Any) {
/// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
guard let layer = layer as? NullCompositionLayer else {
fatalError("init(layer:) Wrong Layer Class")
}
super.init(layer: layer)
}
}

View File

@ -0,0 +1,104 @@
//
// PreCompositionLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/25/19.
//
import Foundation
import QuartzCore
final class PreCompositionLayer: CompositionLayer {
let frameRate: CGFloat
let remappingNode: NodeProperty<Vector1D>?
fileprivate var animationLayers: [CompositionLayer]
init(precomp: PreCompLayerModel,
asset: PrecompAsset,
layerImageProvider: LayerImageProvider,
textProvider: AnimationTextProvider,
fontProvider: AnimationFontProvider,
assetLibrary: AssetLibrary?,
frameRate: CGFloat) {
self.animationLayers = []
if let keyframes = precomp.timeRemapping?.keyframes {
self.remappingNode = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframes))
} else {
self.remappingNode = nil
}
self.frameRate = frameRate
super.init(layer: precomp, size: CGSize(width: precomp.width, height: precomp.height))
contentsLayer.masksToBounds = true
contentsLayer.bounds = CGRect(origin: .zero, size: CGSize(width: precomp.width, height: precomp.height))
let layers = asset.layers.initializeCompositionLayers(assetLibrary: assetLibrary, layerImageProvider: layerImageProvider, textProvider: textProvider, fontProvider: fontProvider, frameRate: frameRate)
var imageLayers = [ImageCompositionLayer]()
var mattedLayer: CompositionLayer? = nil
for layer in layers.reversed() {
layer.bounds = bounds
animationLayers.append(layer)
if let imageLayer = layer as? ImageCompositionLayer {
imageLayers.append(imageLayer)
}
if let matte = mattedLayer {
/// The previous layer requires this layer to be its matte
matte.matteLayer = layer
mattedLayer = nil
continue
}
if let matte = layer.matteType,
(matte == .add || matte == .invert) {
/// We have a layer that requires a matte.
mattedLayer = layer
}
contentsLayer.addSublayer(layer)
}
self.childKeypaths.append(contentsOf: layers)
layerImageProvider.addImageLayers(imageLayers)
}
override init(layer: Any) {
/// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
guard let layer = layer as? PreCompositionLayer else {
fatalError("init(layer:) Wrong Layer Class")
}
self.frameRate = layer.frameRate
self.remappingNode = nil
self.animationLayers = []
super.init(layer: layer)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
let localFrame: CGFloat
if let remappingNode = remappingNode {
remappingNode.update(frame: frame)
localFrame = remappingNode.value.cgFloatValue * frameRate
} else {
localFrame = (frame - startFrame) / timeStretch
}
animationLayers.forEach( { $0.displayWithFrame(frame: localFrame, forceUpdates: forceUpdates) })
}
override var keypathProperties: [String : AnyNodeProperty] {
guard let remappingNode = remappingNode else {
return super.keypathProperties
}
return ["Time Remap" : remappingNode]
}
override func updateRenderScale() {
super.updateRenderScale()
animationLayers.forEach( { $0.renderScale = renderScale } )
}
}

View File

@ -0,0 +1,56 @@
//
// ShapeLayerContainer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/22/19.
//
import Foundation
import CoreGraphics
/**
A CompositionLayer responsible for initializing and rendering shapes
*/
final class ShapeCompositionLayer: CompositionLayer {
let rootNode: AnimatorNode?
let renderContainer: ShapeContainerLayer?
init(shapeLayer: ShapeLayerModel) {
let results = shapeLayer.items.initializeNodeTree()
let renderContainer = ShapeContainerLayer()
self.renderContainer = renderContainer
self.rootNode = results.rootNode
super.init(layer: shapeLayer, size: .zero)
contentsLayer.addSublayer(renderContainer)
for container in results.renderContainers {
renderContainer.insertRenderLayer(container)
}
rootNode?.updateTree(0, forceUpdates: true)
self.childKeypaths.append(contentsOf: results.childrenNodes)
}
override init(layer: Any) {
guard let layer = layer as? ShapeCompositionLayer else {
fatalError("init(layer:) wrong class.")
}
self.rootNode = nil
self.renderContainer = nil
super.init(layer: layer)
}
override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
rootNode?.updateTree(frame, forceUpdates: forceUpdates)
renderContainer?.markRenderUpdates(forFrame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func updateRenderScale() {
super.updateRenderScale()
renderContainer?.renderScale = renderScale
}
}

View File

@ -0,0 +1,48 @@
//
// SolidCompositionLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/25/19.
//
import Foundation
import QuartzCore
final class SolidCompositionLayer: CompositionLayer {
let colorProperty: NodeProperty<Color>?
let solidShape: CAShapeLayer = CAShapeLayer()
init(solid: SolidLayerModel) {
let components = solid.colorHex.hexColorComponents()
self.colorProperty = NodeProperty(provider: SingleValueProvider(Color(r: Double(components.red), g: Double(components.green), b: Double(components.blue), a: 1)))
super.init(layer: solid, size: .zero)
solidShape.path = CGPath(rect: CGRect(x: 0, y: 0, width: solid.width, height: solid.height), transform: nil)
contentsLayer.addSublayer(solidShape)
}
override init(layer: Any) {
/// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
guard let layer = layer as? SolidCompositionLayer else {
fatalError("init(layer:) Wrong Layer Class")
}
self.colorProperty = layer.colorProperty
super.init(layer: layer)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
guard let colorProperty = colorProperty else { return }
colorProperty.update(frame: frame)
solidShape.fillColor = colorProperty.value.cgColorValue
}
override var keypathProperties: [String : AnyNodeProperty] {
guard let colorProperty = colorProperty else { return super.keypathProperties }
return ["Color" : colorProperty]
}
}

View File

@ -0,0 +1,138 @@
//
// TextCompositionLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/25/19.
//
import Foundation
import CoreGraphics
import QuartzCore
import CoreText
/// Needed for NSMutableParagraphStyle...
#if os(OSX)
import AppKit
#else
import UIKit
#endif
extension TextJustification {
var textAlignment: NSTextAlignment {
switch self {
case .left:
return .left
case .right:
return .right
case .center:
return .center
}
}
var caTextAlignement: CATextLayerAlignmentMode {
switch self {
case .left:
return .left
case .right:
return .right
case .center:
return .center
}
}
}
final class TextCompositionLayer: CompositionLayer {
let rootNode: TextAnimatorNode?
let textDocument: KeyframeInterpolator<TextDocument>?
let textLayer: TextLayer = TextLayer()
var textProvider: AnimationTextProvider
var fontProvider: AnimationFontProvider
init(textLayer: TextLayerModel, textProvider: AnimationTextProvider, fontProvider: AnimationFontProvider) {
var rootNode: TextAnimatorNode?
for animator in textLayer.animators {
rootNode = TextAnimatorNode(parentNode: rootNode, textAnimator: animator)
}
self.rootNode = rootNode
self.textDocument = KeyframeInterpolator(keyframes: textLayer.text.keyframes)
self.textProvider = textProvider
self.fontProvider = fontProvider
super.init(layer: textLayer, size: .zero)
contentsLayer.addSublayer(self.textLayer)
self.textLayer.masksToBounds = false
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(layer: Any) {
/// Used for creating shadow model layers. Read More here: https://developer.apple.com/documentation/quartzcore/calayer/1410842-init
guard let layer = layer as? TextCompositionLayer else {
fatalError("init(layer:) Wrong Layer Class")
}
self.rootNode = nil
self.textDocument = nil
self.textProvider = DefaultTextProvider()
self.fontProvider = DefaultFontProvider()
super.init(layer: layer)
}
override func displayContentsWithFrame(frame: CGFloat, forceUpdates: Bool) {
guard let textDocument = textDocument else { return }
textLayer.contentsScale = self.renderScale
let documentUpdate = textDocument.hasUpdate(frame: frame)
let animatorUpdate = rootNode?.updateContents(frame, forceLocalUpdate: forceUpdates) ?? false
guard documentUpdate == true || animatorUpdate == true else { return }
rootNode?.rebuildOutputs(frame: frame)
// Get Text Attributes
let text = textDocument.value(frame: frame) as! TextDocument
let strokeColor = rootNode?.textOutputNode.strokeColor ?? text.strokeColorData?.cgColorValue
let strokeWidth = rootNode?.textOutputNode.strokeWidth ?? CGFloat(text.strokeWidth ?? 0)
let tracking = (CGFloat(text.fontSize) * (rootNode?.textOutputNode.tracking ?? CGFloat(text.tracking))) / 1000.0
let matrix = rootNode?.textOutputNode.xform ?? CATransform3DIdentity
let textString = textProvider.textFor(keypathName: self.keypathName, sourceText: text.text)
let ctFont = fontProvider.fontFor(family: text.fontFamily, size: CGFloat(text.fontSize))
// Set all of the text layer options
textLayer.text = textString
textLayer.font = ctFont
textLayer.alignment = text.justification.textAlignment
textLayer.lineHeight = CGFloat(text.lineHeight)
textLayer.tracking = tracking
if let fillColor = rootNode?.textOutputNode.fillColor {
textLayer.fillColor = fillColor
} else if let fillColor = text.fillColorData?.cgColorValue {
textLayer.fillColor = fillColor
} else {
textLayer.fillColor = nil
}
textLayer.preferredSize = text.textFrameSize?.sizeValue
textLayer.strokeOnTop = text.strokeOverFill ?? false
textLayer.strokeWidth = strokeWidth
textLayer.strokeColor = strokeColor
textLayer.sizeToFit()
textLayer.opacity = Float(rootNode?.textOutputNode.opacity ?? 1)
textLayer.transform = CATransform3DIdentity
textLayer.position = text.textFramePosition?.pointValue ?? CGPoint.zero
textLayer.transform = matrix
}
override func updateRenderScale() {
super.updateRenderScale()
textLayer.contentsScale = self.renderScale
}
}

View File

@ -0,0 +1,81 @@
//
// CompositionLayersInitializer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/25/19.
//
import Foundation
import CoreGraphics
extension Array where Element == LayerModel {
func initializeCompositionLayers(assetLibrary: AssetLibrary?,
layerImageProvider: LayerImageProvider,
textProvider: AnimationTextProvider,
fontProvider: AnimationFontProvider,
frameRate: CGFloat) -> [CompositionLayer] {
var compositionLayers = [CompositionLayer]()
var layerMap = [Int : CompositionLayer]()
/// Organize the assets into a dictionary of [ID : ImageAsset]
var childLayers = [LayerModel]()
for layer in self {
if layer.hidden == true {
let genericLayer = NullCompositionLayer(layer: layer)
compositionLayers.append(genericLayer)
layerMap[layer.index] = genericLayer
} else if let shapeLayer = layer as? ShapeLayerModel {
let shapeContainer = ShapeCompositionLayer(shapeLayer: shapeLayer)
compositionLayers.append(shapeContainer)
layerMap[layer.index] = shapeContainer
} else if let solidLayer = layer as? SolidLayerModel {
let solidContainer = SolidCompositionLayer(solid: solidLayer)
compositionLayers.append(solidContainer)
layerMap[layer.index] = solidContainer
} else if let precompLayer = layer as? PreCompLayerModel,
let assetLibrary = assetLibrary,
let precompAsset = assetLibrary.precompAssets[precompLayer.referenceID] {
let precompContainer = PreCompositionLayer(precomp: precompLayer,
asset: precompAsset,
layerImageProvider: layerImageProvider,
textProvider: textProvider,
fontProvider: fontProvider,
assetLibrary: assetLibrary,
frameRate: frameRate)
compositionLayers.append(precompContainer)
layerMap[layer.index] = precompContainer
} else if let imageLayer = layer as? ImageLayerModel,
let assetLibrary = assetLibrary,
let imageAsset = assetLibrary.imageAssets[imageLayer.referenceID] {
let imageContainer = ImageCompositionLayer(imageLayer: imageLayer, size: CGSize(width: imageAsset.width, height: imageAsset.height))
compositionLayers.append(imageContainer)
layerMap[layer.index] = imageContainer
} else if let textLayer = layer as? TextLayerModel {
let textContainer = TextCompositionLayer(textLayer: textLayer, textProvider: textProvider, fontProvider: fontProvider)
compositionLayers.append(textContainer)
layerMap[layer.index] = textContainer
} else {
let genericLayer = NullCompositionLayer(layer: layer)
compositionLayers.append(genericLayer)
layerMap[layer.index] = genericLayer
}
if layer.parent != nil {
childLayers.append(layer)
}
}
/// Now link children with their parents
for layerModel in childLayers {
if let parentID = layerModel.parent {
let childLayer = layerMap[layerModel.index]
let parentLayer = layerMap[parentID]
childLayer?.transformNode.parentNode = parentLayer?.transformNode
}
}
return compositionLayers
}
}

View File

@ -0,0 +1,57 @@
//
// InvertedMatteLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/28/19.
//
import Foundation
import QuartzCore
/**
A layer that inverses the alpha output of its input layer.
WARNING: This is experimental and probably not very performant.
*/
final class InvertedMatteLayer: CALayer, CompositionLayerDelegate {
let inputMatte: CompositionLayer?
let wrapperLayer = CALayer()
init(inputMatte: CompositionLayer) {
self.inputMatte = inputMatte
super.init()
inputMatte.layerDelegate = self
self.anchorPoint = .zero
self.bounds = inputMatte.bounds
self.setNeedsDisplay()
}
override init(layer: Any) {
guard let layer = layer as? InvertedMatteLayer else {
fatalError("init(layer:) wrong class.")
}
self.inputMatte = nil
super.init(layer: layer)
}
func frameUpdated(frame: CGFloat) {
self.setNeedsDisplay()
self.displayIfNeeded()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(in ctx: CGContext) {
guard let inputMatte = inputMatte else { return }
guard let fillColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [0, 0, 0, 1])
else { return }
ctx.setFillColor(fillColor)
ctx.fill(bounds)
ctx.setBlendMode(.destinationOut)
inputMatte.render(in: ctx)
}
}

View File

@ -0,0 +1,37 @@
//
// LayerFontProvider.swift
// Lottie
//
// Created by Brandon Withrow on 8/5/20.
// Copyright © 2020 YurtvilleProds. All rights reserved.
//
import Foundation
/// Connects a LottieFontProvider to a group of text layers
final class LayerFontProvider {
var fontProvider: AnimationFontProvider {
didSet {
reloadTexts()
}
}
fileprivate(set) var textLayers: [TextCompositionLayer]
init(fontProvider: AnimationFontProvider) {
self.fontProvider = fontProvider
self.textLayers = []
reloadTexts()
}
func addTextLayers(_ layers: [TextCompositionLayer]) {
textLayers += layers
}
func reloadTexts() {
textLayers.forEach {
$0.fontProvider = fontProvider
}
}
}

View File

@ -0,0 +1,49 @@
//
// LayerImageProvider.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/25/19.
//
import Foundation
/// Connects a LottieImageProvider to a group of image layers
final class LayerImageProvider {
var imageProvider: AnimationImageProvider {
didSet {
reloadImages()
}
}
fileprivate(set) var imageLayers: [ImageCompositionLayer]
let imageAssets: [String : ImageAsset]
init(imageProvider: AnimationImageProvider, assets: [String : ImageAsset]?) {
self.imageProvider = imageProvider
self.imageLayers = [ImageCompositionLayer]()
if let assets = assets {
self.imageAssets = assets
} else {
self.imageAssets = [:]
}
reloadImages()
}
func addImageLayers(_ layers: [ImageCompositionLayer]) {
for layer in layers {
if imageAssets[layer.imageReferenceID] != nil {
/// Found a linking asset in our asset library. Add layer
imageLayers.append(layer)
}
}
}
func reloadImages() {
for imageLayer in imageLayers {
if let asset = imageAssets[imageLayer.imageReferenceID] {
imageLayer.image = imageProvider.imageForAsset(asset: asset)
}
}
}
}

View File

@ -0,0 +1,36 @@
//
// LayerTextProvider.swift
// lottie-ios-iOS
//
// Created by Alexandr Goncharov on 07/06/2019.
//
import Foundation
/// Connects a LottieTextProvider to a group of text layers
final class LayerTextProvider {
var textProvider: AnimationTextProvider {
didSet {
reloadTexts()
}
}
fileprivate(set) var textLayers: [TextCompositionLayer]
init(textProvider: AnimationTextProvider) {
self.textProvider = textProvider
self.textLayers = []
reloadTexts()
}
func addTextLayers(_ layers: [TextCompositionLayer]) {
textLayers += layers
}
func reloadTexts() {
textLayers.forEach {
$0.textProvider = textProvider
}
}
}

View File

@ -0,0 +1,128 @@
//
// LayerTransformPropertyMap.swift
// lottie-swift
//
// Created by Brandon Withrow on 2/4/19.
//
import Foundation
import CoreGraphics
import QuartzCore
final class LayerTransformProperties: NodePropertyMap, KeypathSearchable {
init(transform: Transform) {
self.anchor = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.anchorPoint.keyframes))
self.scale = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.scale.keyframes))
self.rotation = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotation.keyframes))
self.opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.opacity.keyframes))
var propertyMap: [String: AnyNodeProperty] = [
"Anchor Point" : anchor,
"Scale" : scale,
"Rotation" : rotation,
"Opacity" : opacity
]
if let positionKeyframesX = transform.positionX?.keyframes,
let positionKeyframesY = transform.positionY?.keyframes {
let xPosition: NodeProperty<Vector1D> = NodeProperty(provider: KeyframeInterpolator(keyframes: positionKeyframesX))
let yPosition: NodeProperty<Vector1D> = NodeProperty(provider: KeyframeInterpolator(keyframes: positionKeyframesY))
propertyMap["X Position"] = xPosition
propertyMap["Y Position"] = yPosition
self.positionX = xPosition
self.positionY = yPosition
self.position = nil
} else if let positionKeyframes = transform.position?.keyframes {
let position: NodeProperty<Vector3D> = NodeProperty(provider: KeyframeInterpolator(keyframes: positionKeyframes))
propertyMap["Position"] = position
self.position = position
self.positionX = nil
self.positionY = nil
} else {
self.position = nil
self.positionY = nil
self.positionX = nil
}
self.keypathProperties = propertyMap
self.properties = Array(propertyMap.values)
}
let keypathProperties: [String : AnyNodeProperty]
var keypathName: String = "Transform"
var childKeypaths: [KeypathSearchable] {
return []
}
let properties: [AnyNodeProperty]
let anchor: NodeProperty<Vector3D>
let scale: NodeProperty<Vector3D>
let rotation: NodeProperty<Vector1D>
let position: NodeProperty<Vector3D>?
let positionX: NodeProperty<Vector1D>?
let positionY: NodeProperty<Vector1D>?
let opacity: NodeProperty<Vector1D>
}
class LayerTransformNode: AnimatorNode {
let outputNode: NodeOutput = PassThroughOutputNode(parent: nil)
init(transform: Transform) {
self.transformProperties = LayerTransformProperties(transform: transform)
}
let transformProperties: LayerTransformProperties
// MARK: Animator Node Protocol
var propertyMap: NodePropertyMap & KeypathSearchable {
return transformProperties
}
var parentNode: AnimatorNode?
var hasLocalUpdates: Bool = false
var hasUpstreamUpdates: Bool = false
var lastUpdateFrame: CGFloat? = nil
var isEnabled: Bool = true
func shouldRebuildOutputs(frame: CGFloat) -> Bool {
return hasLocalUpdates || hasUpstreamUpdates
}
func rebuildOutputs(frame: CGFloat) {
opacity = Float(transformProperties.opacity.value.cgFloatValue) * 0.01
let position: CGPoint
if let point = transformProperties.position?.value.pointValue {
position = point
} else if let xPos = transformProperties.positionX?.value.cgFloatValue,
let yPos = transformProperties.positionY?.value.cgFloatValue {
position = CGPoint(x: xPos, y: yPos)
} else {
position = .zero
}
localTransform = CATransform3D.makeTransform(anchor: transformProperties.anchor.value.pointValue,
position: position,
scale: transformProperties.scale.value.sizeValue,
rotation: transformProperties.rotation.value.cgFloatValue,
skew: nil,
skewAxis: nil)
if let parentNode = parentNode as? LayerTransformNode {
globalTransform = CATransform3DConcat(localTransform, parentNode.globalTransform)
} else {
globalTransform = localTransform
}
}
var opacity: Float = 1
var localTransform: CATransform3D = CATransform3DIdentity
var globalTransform: CATransform3D = CATransform3DIdentity
}

View File

@ -0,0 +1,304 @@
//
// TextLayer.swift
// Pods
//
// Created by Brandon Withrow on 8/3/20.
//
import Foundation
import CoreText
import QuartzCore
import CoreGraphics
/// Needed for NSMutableParagraphStyle...
#if os(OSX)
import AppKit
#else
import UIKit
#endif
final class TextLayer: CALayer {
public var text: String? {
didSet {
needsContentUpdate = true
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public var font: CTFont? {
didSet {
needsContentUpdate = true
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public var alignment: NSTextAlignment = .left {
didSet {
needsContentUpdate = true
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public var lineHeight: CGFloat = 0 {
didSet {
needsContentUpdate = true
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public var tracking: CGFloat = 0 {
didSet {
needsContentUpdate = true
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public var fillColor: CGColor? {
didSet {
needsContentUpdate = true
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public var strokeColor: CGColor? {
didSet {
needsContentUpdate = true
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public var strokeWidth: CGFloat = 0 {
didSet {
needsContentUpdate = true
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public var strokeOnTop: Bool = false {
didSet {
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public var preferredSize: CGSize? {
didSet {
needsContentUpdate = true
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
public func sizeToFit() {
updateTextContent()
bounds = drawingRect
anchorPoint = drawingAnchor
self.setNeedsLayout()
self.setNeedsDisplay()
}
override func action(forKey event: String) -> CAAction? {
return nil
}
// Draws Debug colors for the font alignment.
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
private func drawDebug(_ ctx: CGContext) {
if let font = font {
let ascent = CTFontGetAscent(font)
let descent = CTFontGetDescent(font)
let capHeight = CTFontGetCapHeight(font)
let leading = CTFontGetLeading(font)
// Ascent Red
ctx.setFillColor(CGColor(srgbRed: 1, green: 0, blue: 0, alpha: 0.5))
ctx.fill(CGRect(x:0, y:0, width:drawingRect.width, height:ascent))
// Descent Blue
ctx.setFillColor(CGColor(srgbRed: 0, green: 0, blue: 1, alpha: 0.5))
ctx.fill(CGRect(x:0, y:ascent, width:drawingRect.width, height:descent))
// Leading Yellow
ctx.setFillColor(CGColor(srgbRed: 1, green: 1, blue: 0, alpha: 0.5))
ctx.fill(CGRect(x:0, y:ascent+descent, width:drawingRect.width, height:leading))
// Cap height Green
ctx.setFillColor(CGColor(srgbRed: 0, green: 1, blue: 0, alpha: 0.5))
ctx.fill(CGRect(x:0, y:ascent - capHeight, width:drawingRect.width, height:capHeight))
if drawingRect.height - ascent+descent+leading > 0 {
// Remainder
ctx.setFillColor(CGColor(srgbRed: 0, green: 1, blue: 1, alpha: 0.5))
ctx.fill(CGRect(x:0, y:ascent+descent+leading, width:drawingRect.width, height:drawingRect.height - ascent+descent+leading))
}
}
}
override func draw(in ctx: CGContext) {
guard let attributedString = attributedString else { return }
updateTextContent()
guard fillFrameSetter != nil || strokeFrameSetter != nil else { return }
ctx.textMatrix = .identity
ctx.setAllowsAntialiasing(true)
ctx.setAllowsFontSmoothing(true)
ctx.setAllowsFontSubpixelPositioning(true)
ctx.setAllowsFontSubpixelQuantization(true)
ctx.setShouldAntialias(true)
ctx.setShouldSmoothFonts(true)
ctx.setShouldSubpixelPositionFonts(true)
ctx.setShouldSubpixelQuantizeFonts(true)
ctx.translateBy(x: 0, y: drawingRect.height)
ctx.scaleBy(x: 1.0, y: -1.0)
let drawingPath = CGPath(rect: drawingRect, transform: nil)
let fillFrame: CTFrame?
if let setter = fillFrameSetter {
fillFrame = CTFramesetterCreateFrame(setter, CFRangeMake(0, attributedString.length), drawingPath, nil)
} else {
fillFrame = nil
}
let strokeFrame: CTFrame?
if let setter = strokeFrameSetter {
strokeFrame = CTFramesetterCreateFrame(setter, CFRangeMake(0, attributedString.length), drawingPath, nil)
} else {
strokeFrame = nil
}
if !strokeOnTop, let strokeFrame = strokeFrame {
CTFrameDraw(strokeFrame, ctx)
}
if let fillFrame = fillFrame {
CTFrameDraw(fillFrame, ctx)
}
if strokeOnTop, let strokeFrame = strokeFrame {
CTFrameDraw(strokeFrame, ctx)
}
}
private var drawingRect: CGRect = .zero
private var drawingAnchor: CGPoint = .zero
private var fillFrameSetter: CTFramesetter?
private var attributedString: NSAttributedString?
private var strokeFrameSetter: CTFramesetter?
private var needsContentUpdate: Bool = false
private func updateTextContent() {
guard needsContentUpdate else { return }
needsContentUpdate = false
guard let font = font, let text = text, text.count > 0, (fillColor != nil || strokeColor != nil) else {
drawingRect = .zero
drawingAnchor = .zero
attributedString = nil
fillFrameSetter = nil
strokeFrameSetter = nil
return
}
// Get Font properties
let ascent = CTFontGetAscent(font)
let descent = CTFontGetDescent(font)
let capHeight = CTFontGetCapHeight(font)
let leading = CTFontGetLeading(font)
let minLineHeight = -(ascent + descent + leading)
// Calculate line spacing
let lineSpacing = max(CGFloat(minLineHeight) + lineHeight, CGFloat(minLineHeight))
// Build Attributes
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = lineSpacing
paragraphStyle.lineHeightMultiple = 1
paragraphStyle.maximumLineHeight = ascent+descent+leading
paragraphStyle.alignment = alignment
paragraphStyle.lineBreakMode = NSLineBreakMode.byWordWrapping
var attributes: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.ligature: 0,
NSAttributedString.Key.font: font,
NSAttributedString.Key.kern: tracking,
NSAttributedString.Key.paragraphStyle: paragraphStyle
]
if let fillColor = fillColor {
attributes[NSAttributedString.Key.foregroundColor] = fillColor
}
let attrString = NSAttributedString(string: text, attributes: attributes)
attributedString = attrString
if fillColor != nil {
let setter = CTFramesetterCreateWithAttributedString(attrString as CFAttributedString)
fillFrameSetter = setter
} else {
fillFrameSetter = nil
}
if let strokeColor = strokeColor {
attributes[NSAttributedString.Key.foregroundColor] = nil
attributes[NSAttributedString.Key.strokeWidth] = strokeWidth
attributes[NSAttributedString.Key.strokeColor] = strokeColor
let strokeAttributedString = NSAttributedString(string: text, attributes: attributes)
strokeFrameSetter = CTFramesetterCreateWithAttributedString(strokeAttributedString as CFAttributedString)
} else {
strokeFrameSetter = nil
strokeWidth = 0
}
guard let setter = fillFrameSetter ?? strokeFrameSetter else {
return
}
// Calculate drawing size and anchor offset
let textAnchor: CGPoint
if let preferredSize = preferredSize {
drawingRect = CGRect(origin: .zero, size: preferredSize)
drawingRect.size.height += (ascent - capHeight)
drawingRect.size.height += descent
textAnchor = CGPoint(x: 0, y: (ascent-capHeight))
} else {
let size = CTFramesetterSuggestFrameSizeWithConstraints(
setter,
CFRange(location: 0, length: attrString.length),
nil,
CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude),
nil
)
switch alignment {
case .left:
textAnchor = CGPoint(x: 0, y: ascent)
case .right:
textAnchor = CGPoint(x: size.width, y: ascent)
case .center:
textAnchor = CGPoint(x: size.width * 0.5, y: ascent)
default:
textAnchor = .zero
}
drawingRect = CGRect(x: 0, y: 0, width: ceil(size.width),
height: ceil(size.height))
}
// Now Calculate Anchor
drawingAnchor = CGPoint(x: textAnchor.x.remap(fromLow: 0, fromHigh: drawingRect.size.width, toLow: 0, toHigh: 1),
y: textAnchor.y.remap(fromLow: 0, fromHigh: drawingRect.size.height, toLow: 0, toHigh: 1))
if fillFrameSetter != nil && strokeFrameSetter != nil {
drawingRect.size.width += strokeWidth
drawingRect.size.height += strokeWidth
}
}
}

View File

@ -0,0 +1,107 @@
//
// Animation.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/7/19.
//
import Foundation
public enum CoordinateSpace: Int, Codable {
case type2d
case type3d
}
/**
The `Animation` model is the top level model object in Lottie.
An `Animation` holds all of the animation data backing a Lottie Animation.
Codable, see JSON schema [here](https://github.com/airbnb/lottie-web/tree/master/docs/json).
*/
public final class Animation: Codable {
/// The version of the JSON Schema.
let version: String
/// The coordinate space of the composition.
let type: CoordinateSpace
/// The start time of the composition in frameTime.
public let startFrame: AnimationFrameTime
/// The end time of the composition in frameTime.
public let endFrame: AnimationFrameTime
/// The frame rate of the composition.
public let framerate: Double
/// The height of the composition in points.
let width: Int
/// The width of the composition in points.
let height: Int
/// The list of animation layers
let layers: [LayerModel]
/// The list of glyphs used for text rendering
let glyphs: [Glyph]?
/// The list of fonts used for text rendering
let fonts: FontList?
/// Asset Library
let assetLibrary: AssetLibrary?
/// Markers
let markers: [Marker]?
let markerMap: [String : Marker]?
/// Return all marker names, in order, or an empty list if none are specified
public var markerNames: [String] {
guard let markers = markers else { return [] }
return markers.map { $0.name }
}
enum CodingKeys : String, CodingKey {
case version = "v"
case type = "ddd"
case startFrame = "ip"
case endFrame = "op"
case framerate = "fr"
case width = "w"
case height = "h"
case layers = "layers"
case glyphs = "chars"
case fonts = "fonts"
case assetLibrary = "assets"
case markers = "markers"
}
required public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Animation.CodingKeys.self)
self.version = try container.decode(String.self, forKey: .version)
self.type = try container.decodeIfPresent(CoordinateSpace.self, forKey: .type) ?? .type2d
self.startFrame = try container.decode(AnimationFrameTime.self, forKey: .startFrame)
self.endFrame = try container.decode(AnimationFrameTime.self, forKey: .endFrame)
self.framerate = try container.decode(Double.self, forKey: .framerate)
self.width = try container.decode(Int.self, forKey: .width)
self.height = try container.decode(Int.self, forKey: .height)
self.layers = try container.decode([LayerModel].self, ofFamily: LayerType.self, forKey: .layers)
self.glyphs = try container.decodeIfPresent([Glyph].self, forKey: .glyphs)
self.fonts = try container.decodeIfPresent(FontList.self, forKey: .fonts)
self.assetLibrary = try container.decodeIfPresent(AssetLibrary.self, forKey: .assetLibrary)
self.markers = try container.decodeIfPresent([Marker].self, forKey: .markers)
if let markers = markers {
var markerMap: [String : Marker] = [:]
for marker in markers {
markerMap[marker.name] = marker
}
self.markerMap = markerMap
} else {
self.markerMap = nil
}
}
}

View File

@ -0,0 +1,27 @@
//
// Asset.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/9/19.
//
import Foundation
public class Asset: Codable {
/// The ID of the asset
public let id: String
private enum CodingKeys : String, CodingKey {
case id = "id"
}
required public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Asset.CodingKeys.self)
if let id = try? container.decode(String.self, forKey: .id) {
self.id = id
} else {
self.id = String(try container.decode(Int.self, forKey: .id))
}
}
}

View File

@ -0,0 +1,48 @@
//
// AssetLibrary.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/9/19.
//
import Foundation
final class AssetLibrary: Codable {
/// The Assets
let assets: [String : Asset]
let imageAssets: [String : ImageAsset]
let precompAssets: [String : PrecompAsset]
required init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
var containerForKeys = container
var decodedAssets = [String : Asset]()
var imageAssets = [String : ImageAsset]()
var precompAssets = [String : PrecompAsset]()
while !container.isAtEnd {
let keyContainer = try containerForKeys.nestedContainer(keyedBy: PrecompAsset.CodingKeys.self)
if keyContainer.contains(.layers) {
let precompAsset = try container.decode(PrecompAsset.self)
decodedAssets[precompAsset.id] = precompAsset
precompAssets[precompAsset.id] = precompAsset
} else {
let imageAsset = try container.decode(ImageAsset.self)
decodedAssets[imageAsset.id] = imageAsset
imageAssets[imageAsset.id] = imageAsset
}
}
self.assets = decodedAssets
self.precompAssets = precompAssets
self.imageAssets = imageAssets
}
func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(contentsOf: Array(assets.values))
}
}

View File

@ -0,0 +1,48 @@
//
// ImageAsset.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/9/19.
//
import Foundation
public final class ImageAsset: Asset {
/// Image name
public let name: String
/// Image Directory
public let directory: String
/// Image Size
public let width: Double
public let height: Double
enum CodingKeys : String, CodingKey {
case name = "p"
case directory = "u"
case width = "w"
case height = "h"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ImageAsset.CodingKeys.self)
self.name = try container.decode(String.self, forKey: .name)
self.directory = try container.decode(String.self, forKey: .directory)
self.width = try container.decode(Double.self, forKey: .width)
self.height = try container.decode(Double.self, forKey: .height)
try super.init(from: decoder)
}
override public func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
try container.encode(directory, forKey: .directory)
try container.encode(width, forKey: .width)
try container.encode(height, forKey: .height)
}
}

View File

@ -0,0 +1,30 @@
//
// PrecompAsset.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/9/19.
//
import Foundation
final class PrecompAsset: Asset {
/// Layers of the precomp
let layers: [LayerModel]
enum CodingKeys : String, CodingKey {
case layers = "layers"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: PrecompAsset.CodingKeys.self)
self.layers = try container.decode([LayerModel].self, ofFamily: LayerType.self, forKey: .layers)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(layers, forKey: .layers)
}
}

View File

@ -0,0 +1,40 @@
// From: https://medium.com/@kewindannerfjordremeczki/swift-4-0-decodable-heterogeneous-collections-ecc0e6b468cf
import Foundation
/// To support a new class family, create an enum that conforms to this protocol and contains the different types.
protocol ClassFamily: Decodable {
/// The discriminator key.
static var discriminator: Discriminator { get }
/// Returns the class type of the object corresponding to the value.
func getType() -> AnyObject.Type
}
/// Discriminator key enum used to retrieve discriminator fields in JSON payloads.
enum Discriminator: String, CodingKey {
case type = "ty"
}
extension KeyedDecodingContainer {
/// Decode a heterogeneous list of objects for a given family.
/// - Parameters:
/// - heterogeneousType: The decodable type of the list.
/// - family: The ClassFamily enum for the type family.
/// - key: The CodingKey to look up the list in the current container.
/// - Returns: The resulting list of heterogeneousType elements.
func decode<T : Decodable, U : ClassFamily>(_ heterogeneousType: [T].Type, ofFamily family: U.Type, forKey key: K) throws -> [T] {
var container = try self.nestedUnkeyedContainer(forKey: key)
var list = [T]()
var tmpContainer = container
while !container.isAtEnd {
let typeContainer = try container.nestedContainer(keyedBy: Discriminator.self)
let family: U = try typeContainer.decode(U.self, forKey: U.discriminator)
if let type = family.getType() as? T.Type {
list.append(try tmpContainer.decode(type))
}
}
return list
}
}

View File

@ -0,0 +1,128 @@
//
// Keyframe.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/7/19.
//
import Foundation
import CoreGraphics
/**
Keyframe represents a point in time and is the container for datatypes.
Note: This is a parent class and should not be used directly.
*/
final class Keyframe<T: Interpolatable> {
/// The value of the keyframe
let value: T
/// The time in frames of the keyframe.
let time: CGFloat
/// A hold keyframe freezes interpolation until the next keyframe that is not a hold.
let isHold: Bool
/// The in tangent for the time interpolation curve.
let inTangent: Vector2D?
/// The out tangent for the time interpolation curve.
let outTangent: Vector2D?
/// The spacial in tangent of the vector.
let spatialInTangent: Vector3D?
/// The spacial out tangent of the vector.
let spatialOutTangent: Vector3D?
/// Initialize a value-only keyframe with no time data.
init(_ value: T,
spatialInTangent: Vector3D? = nil,
spatialOutTangent: Vector3D? = nil) {
self.value = value
self.time = 0
self.isHold = true
self.inTangent = nil
self.outTangent = nil
self.spatialInTangent = spatialInTangent
self.spatialOutTangent = spatialOutTangent
}
/// Initialize a keyframe
init(value: T,
time: Double,
isHold: Bool,
inTangent: Vector2D?,
outTangent: Vector2D?,
spatialInTangent: Vector3D? = nil,
spatialOutTangent: Vector3D? = nil) {
self.value = value
self.time = CGFloat(time)
self.isHold = isHold
self.outTangent = outTangent
self.inTangent = inTangent
self.spatialInTangent = spatialInTangent
self.spatialOutTangent = spatialOutTangent
}
}
/**
A generic class used to parse and remap keyframe json.
Keyframe json has a couple of different variations and formats depending on the
type of keyframea and also the version of the JSON. By parsing the raw data
we can reconfigure it into a constant format.
*/
final class KeyframeData<T: Codable>: Codable {
/// The start value of the keyframe
let startValue: T?
/// The End value of the keyframe. Note: Newer versions animation json do not have this field.
let endValue: T?
/// The time in frames of the keyframe.
let time: Double?
/// A hold keyframe freezes interpolation until the next keyframe that is not a hold.
let hold: Int?
/// The in tangent for the time interpolation curve.
let inTangent: Vector2D?
/// The out tangent for the time interpolation curve.
let outTangent: Vector2D?
/// The spacial in tangent of the vector.
let spatialInTangent: Vector3D?
/// The spacial out tangent of the vector.
let spatialOutTangent:Vector3D?
init(startValue: T?,
endValue: T?,
time: Double?,
hold: Int?,
inTangent: Vector2D?,
outTangent: Vector2D?,
spatialInTangent: Vector3D?,
spatialOutTangent: Vector3D?) {
self.startValue = startValue
self.endValue = endValue
self.time = time
self.hold = hold
self.inTangent = inTangent
self.outTangent = outTangent
self.spatialInTangent = spatialInTangent
self.spatialOutTangent = spatialOutTangent
}
enum CodingKeys : String, CodingKey {
case startValue = "s"
case endValue = "e"
case time = "t"
case hold = "h"
case inTangent = "i"
case outTangent = "o"
case spatialInTangent = "ti"
case spatialOutTangent = "to"
}
var isHold: Bool {
if let hold = hold {
return hold > 0
}
return false
}
}

View File

@ -0,0 +1,108 @@
//
// KeyframeGroup.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/14/19.
//
import Foundation
/**
Used for coding/decoding a group of Keyframes by type.
Keyframe data is wrapped in a dictionary { "k" : KeyframeData }.
The keyframe data can either be an array of keyframes or, if no animation is present, the raw value.
This helper object is needed to properly decode the json.
*/
final class KeyframeGroup<T>: Codable where T: Codable, T: Interpolatable {
let keyframes: ContiguousArray<Keyframe<T>>
private enum KeyframeWrapperKey: String, CodingKey {
case keyframeData = "k"
}
init(keyframes: ContiguousArray<Keyframe<T>>) {
self.keyframes = keyframes
}
init(_ value: T) {
self.keyframes = [Keyframe(value)]
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: KeyframeWrapperKey.self)
if let keyframeData: T = try? container.decode(T.self, forKey: .keyframeData) {
/// Try to decode raw value; No keyframe data.
self.keyframes = [Keyframe<T>(keyframeData)]
} else {
/**
Decode and array of keyframes.
Body Movin and Lottie deal with keyframes in different ways.
A keyframe object in Body movin defines a span of time with a START
and an END, from the current keyframe time to the next keyframe time.
A keyframe object in Lottie defines a singular point in time/space.
This point has an in-tangent and an out-tangent.
To properly decode this we must iterate through keyframes while holding
reference to the previous keyframe.
*/
var keyframesContainer = try container.nestedUnkeyedContainer(forKey: .keyframeData)
var keyframes = ContiguousArray<Keyframe<T>>()
var previousKeyframeData: KeyframeData<T>?
while(!keyframesContainer.isAtEnd) {
// Ensure that Time and Value are present.
let keyframeData = try keyframesContainer.decode(KeyframeData<T>.self)
guard let value: T = keyframeData.startValue ?? previousKeyframeData?.endValue,
let time = keyframeData.time else {
/// Missing keyframe data. JSON must be corrupt.
throw DecodingError.dataCorruptedError(forKey: KeyframeWrapperKey.keyframeData, in: container, debugDescription: "Missing keyframe data.")
}
keyframes.append(Keyframe<T>(value: value,
time: time,
isHold: keyframeData.isHold,
inTangent: previousKeyframeData?.inTangent,
outTangent: keyframeData.outTangent,
spatialInTangent: previousKeyframeData?.spatialInTangent,
spatialOutTangent: keyframeData.spatialOutTangent))
previousKeyframeData = keyframeData
}
self.keyframes = keyframes
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: KeyframeWrapperKey.self)
if keyframes.count == 1 {
let keyframe = keyframes[0]
try container.encode(keyframe.value, forKey: .keyframeData)
} else {
var keyframeContainer = container.nestedUnkeyedContainer(forKey: .keyframeData)
for i in 1..<keyframes.endIndex {
let keyframe = keyframes[i-1]
let nextKeyframe = keyframes[i]
let keyframeData = KeyframeData<T>(startValue: keyframe.value,
endValue: nextKeyframe.value,
time: Double(keyframe.time),
hold: keyframe.isHold ? 1 : nil,
inTangent: nextKeyframe.inTangent,
outTangent: keyframe.outTangent,
spatialInTangent: nil,
spatialOutTangent: nil)
try keyframeContainer.encode(keyframeData)
}
}
}
}

View File

@ -0,0 +1,32 @@
//
// ImageLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// A layer that holds an image.
final class ImageLayerModel: LayerModel {
/// The reference ID of the image.
let referenceID: String
private enum CodingKeys : String, CodingKey {
case referenceID = "refId"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ImageLayerModel.CodingKeys.self)
self.referenceID = try container.decode(String.self, forKey: .referenceID)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(referenceID, forKey: .referenceID)
}
}

View File

@ -0,0 +1,150 @@
//
// Layer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/7/19.
//
import Foundation
/// Used for mapping a heterogeneous list to classes for parsing.
extension LayerType: ClassFamily {
static var discriminator: Discriminator = .type
func getType() -> AnyObject.Type {
switch self {
case .precomp:
return PreCompLayerModel.self
case .solid:
return SolidLayerModel.self
case .image:
return ImageLayerModel.self
case .null:
return LayerModel.self
case .shape:
return ShapeLayerModel.self
case .text:
return TextLayerModel.self
}
}
}
public enum LayerType: Int, Codable {
case precomp
case solid
case image
case null
case shape
case text
public init(from decoder: Decoder) throws {
self = try LayerType(rawValue: decoder.singleValueContainer().decode(RawValue.self)) ?? .null
}
}
public enum MatteType: Int, Codable {
case none
case add
case invert
case unknown
}
public enum BlendMode: Int, Codable {
case normal
case multiply
case screen
case overlay
case darken
case lighten
case colorDodge
case colorBurn
case hardLight
case softLight
case difference
case exclusion
case hue
case saturation
case color
case luminosity
}
/**
A base top container for shapes, images, and other view objects.
*/
class LayerModel: Codable {
/// The readable name of the layer
let name: String
/// The index of the layer
let index: Int
/// The type of the layer.
let type: LayerType
/// The coordinate space
let coordinateSpace: CoordinateSpace
/// The in time of the layer in frames.
let inFrame: Double
/// The out time of the layer in frames.
let outFrame: Double
/// The start time of the layer in frames.
let startTime: Double
/// The transform of the layer
let transform: Transform
/// The index of the parent layer, if applicable.
let parent: Int?
/// The blending mode for the layer
let blendMode: BlendMode
/// An array of masks for the layer.
let masks: [Mask]?
/// A number that stretches time by a multiplier
let timeStretch: Double
/// The type of matte if any.
let matte: MatteType?
let hidden: Bool
private enum CodingKeys : String, CodingKey {
case name = "nm"
case index = "ind"
case type = "ty"
case coordinateSpace = "ddd"
case inFrame = "ip"
case outFrame = "op"
case startTime = "st"
case transform = "ks"
case parent = "parent"
case blendMode = "bm"
case masks = "masksProperties"
case timeStretch = "sr"
case matte = "tt"
case hidden = "hd"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: LayerModel.CodingKeys.self)
self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Layer"
self.index = try container.decode(Int.self, forKey: .index)
self.type = try container.decode(LayerType.self, forKey: .type)
self.coordinateSpace = try container.decodeIfPresent(CoordinateSpace.self, forKey: .coordinateSpace) ?? .type2d
self.inFrame = try container.decode(Double.self, forKey: .inFrame)
self.outFrame = try container.decode(Double.self, forKey: .outFrame)
self.startTime = try container.decode(Double.self, forKey: .startTime)
self.transform = try container.decode(Transform.self, forKey: .transform)
self.parent = try container.decodeIfPresent(Int.self, forKey: .parent)
self.blendMode = try container.decodeIfPresent(BlendMode.self, forKey: .blendMode) ?? .normal
self.masks = try container.decodeIfPresent([Mask].self, forKey: .masks)
self.timeStretch = try container.decodeIfPresent(Double.self, forKey: .timeStretch) ?? 1
self.matte = try container.decodeIfPresent(MatteType.self, forKey: .matte)
self.hidden = try container.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
}
}

View File

@ -0,0 +1,50 @@
//
// PreCompLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// A layer that holds another animation composition.
final class PreCompLayerModel: LayerModel {
/// The reference ID of the precomp.
let referenceID: String
/// A value that remaps time over time.
let timeRemapping: KeyframeGroup<Vector1D>?
/// Precomp Width
let width: Double
/// Precomp Height
let height: Double
private enum CodingKeys : String, CodingKey {
case referenceID = "refId"
case timeRemapping = "tm"
case width = "w"
case height = "h"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: PreCompLayerModel.CodingKeys.self)
self.referenceID = try container.decode(String.self, forKey: .referenceID)
self.timeRemapping = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .timeRemapping)
self.width = try container.decode(Double.self, forKey: .width)
self.height = try container.decode(Double.self, forKey: .height)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(referenceID, forKey: .referenceID)
try container.encode(timeRemapping, forKey: .timeRemapping)
try container.encode(width, forKey: .width)
try container.encode(height, forKey: .height)
}
}

View File

@ -0,0 +1,32 @@
//
// ShapeLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// A layer that holds vector shape objects.
final class ShapeLayerModel: LayerModel {
/// A list of shape items.
let items: [ShapeItem]
private enum CodingKeys : String, CodingKey {
case items = "shapes"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ShapeLayerModel.CodingKeys.self)
self.items = try container.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .items)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.items, forKey: .items)
}
}

View File

@ -0,0 +1,44 @@
//
// SolidLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// A layer that holds a solid color.
final class SolidLayerModel: LayerModel {
/// The color of the solid in Hex // Change to value provider.
let colorHex: String
/// The Width of the color layer
let width: Double
/// The height of the color layer
let height: Double
private enum CodingKeys : String, CodingKey {
case colorHex = "sc"
case width = "sw"
case height = "sh"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: SolidLayerModel.CodingKeys.self)
self.colorHex = try container.decode(String.self, forKey: .colorHex)
self.width = try container.decode(Double.self, forKey: .width)
self.height = try container.decode(Double.self, forKey: .height)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(colorHex, forKey: .colorHex)
try container.encode(width, forKey: .width)
try container.encode(height, forKey: .height)
}
}

View File

@ -0,0 +1,44 @@
//
// TextLayer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// A layer that holds text.
final class TextLayerModel: LayerModel {
/// The text for the layer
let text: KeyframeGroup<TextDocument>
/// Text animators
let animators: [TextAnimator]
private enum CodingKeys : String, CodingKey {
case textGroup = "t"
}
private enum TextCodingKeys : String, CodingKey {
case text = "d"
case animators = "a"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: TextLayerModel.CodingKeys.self)
let textContainer = try container.nestedContainer(keyedBy: TextCodingKeys.self, forKey: .textGroup)
self.text = try textContainer.decode(KeyframeGroup<TextDocument>.self, forKey: .text)
self.animators = try textContainer.decode([TextAnimator].self, forKey: .animators)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
var textContainer = container.nestedContainer(keyedBy: TextCodingKeys.self, forKey: .textGroup)
try textContainer.encode(text, forKey: .text)
try textContainer.encode(animators, forKey: .animators)
}
}

View File

@ -0,0 +1,24 @@
//
// DashPattern.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/22/19.
//
import Foundation
enum DashElementType: String, Codable {
case offset = "o"
case dash = "d"
case gap = "g"
}
final class DashElement: Codable {
let type: DashElementType
let value: KeyframeGroup<Vector1D>
enum CodingKeys : String, CodingKey {
case type = "n"
case value = "v"
}
}

View File

@ -0,0 +1,23 @@
//
// Marker.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/9/19.
//
import Foundation
/// A time marker
final class Marker: Codable {
/// The Marker Name
let name: String
/// The Frame time of the marker
let frameTime: AnimationFrameTime
enum CodingKeys : String, CodingKey {
case name = "cm"
case frameTime = "tm"
}
}

View File

@ -0,0 +1,48 @@
//
// Mask.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
enum MaskMode: String, Codable {
case add = "a"
case subtract = "s"
case intersect = "i"
case lighten = "l"
case darken = "d"
case difference = "f"
case none = "n"
}
final class Mask: Codable {
let mode: MaskMode
let opacity: KeyframeGroup<Vector1D>
let shape: KeyframeGroup<BezierPath>
let inverted: Bool
let expansion: KeyframeGroup<Vector1D>
enum CodingKeys : String, CodingKey {
case mode = "mode"
case opacity = "o"
case inverted = "inv"
case shape = "pt"
case expansion = "x"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Mask.CodingKeys.self)
self.mode = try container.decodeIfPresent(MaskMode.self, forKey: .mode) ?? .add
self.opacity = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .opacity) ?? KeyframeGroup(Vector1D(100))
self.shape = try container.decode(KeyframeGroup<BezierPath>.self, forKey: .shape)
self.inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false
self.expansion = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .expansion) ?? KeyframeGroup(Vector1D(0))
}
}

View File

@ -0,0 +1,105 @@
//
// Transform.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/7/19.
//
import Foundation
/// The animatable transform for a layer. Controls position, rotation, scale, and opacity.
final class Transform: Codable {
/// The anchor point of the transform.
let anchorPoint: KeyframeGroup<Vector3D>
/// The position of the transform. This is nil if the position data was split.
let position: KeyframeGroup<Vector3D>?
/// The positionX of the transform. This is nil if the position property is set.
let positionX: KeyframeGroup<Vector1D>?
/// The positionY of the transform. This is nil if the position property is set.
let positionY: KeyframeGroup<Vector1D>?
/// The scale of the transform
let scale: KeyframeGroup<Vector3D>
/// The rotation of the transform. Note: This is single dimensional rotation.
let rotation: KeyframeGroup<Vector1D>
/// The opacity of the transform.
let opacity: KeyframeGroup<Vector1D>
/// Should always be nil.
let rotationZ: KeyframeGroup<Vector1D>?
enum CodingKeys : String, CodingKey {
case anchorPoint = "a"
case position = "p"
case positionX = "px"
case positionY = "py"
case scale = "s"
case rotation = "r"
case rotationZ = "rz"
case opacity = "o"
}
enum PositionCodingKeys : String, CodingKey {
case split = "s"
case positionX = "x"
case positionY = "y"
}
required init(from decoder: Decoder) throws {
/**
This manual override of decode is required because we want to throw an error
in the case that there is not position data.
*/
let container = try decoder.container(keyedBy: Transform.CodingKeys.self)
// AnchorPoint
self.anchorPoint = try container.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .anchorPoint) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
// Position
if container.contains(.positionX), container.contains(.positionY) {
// Position dimensions are split into two keyframe groups
self.positionX = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .positionX)
self.positionY = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .positionY)
self.position = nil
} else if let positionKeyframes = try? container.decode(KeyframeGroup<Vector3D>.self, forKey: .position) {
// Position dimensions are a single keyframe group.
self.position = positionKeyframes
self.positionX = nil
self.positionY = nil
} else if let positionContainer = try? container.nestedContainer(keyedBy: PositionCodingKeys.self, forKey: .position),
let positionX = try? positionContainer.decode(KeyframeGroup<Vector1D>.self, forKey: .positionX),
let positionY = try? positionContainer.decode(KeyframeGroup<Vector1D>.self, forKey: .positionY) {
/// Position keyframes are split and nested.
self.positionX = positionX
self.positionY = positionY
self.position = nil
} else {
/// Default value.
self.position = KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
self.positionX = nil
self.positionY = nil
}
// Scale
self.scale = try container.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .scale) ?? KeyframeGroup(Vector3D(x: Double(100), y: 100, z: 100))
// Rotation
if let rotationZ = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .rotationZ) {
self.rotation = rotationZ
} else {
self.rotation = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .rotation) ?? KeyframeGroup(Vector1D(0))
}
self.rotationZ = nil
// Opacity
self.opacity = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .opacity) ?? KeyframeGroup(Vector1D(100))
}
}

View File

@ -0,0 +1,50 @@
//
// EllipseItem.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
enum PathDirection: Int, Codable {
case clockwise = 1
case userSetClockwise = 2
case counterClockwise = 3
}
/// An item that define an ellipse shape
final class Ellipse: ShapeItem {
/// The direction of the ellipse.
let direction: PathDirection
/// The position of the ellipse
let position: KeyframeGroup<Vector3D>
/// The size of the ellipse
let size: KeyframeGroup<Vector3D>
private enum CodingKeys : String, CodingKey {
case direction = "d"
case position = "p"
case size = "s"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Ellipse.CodingKeys.self)
self.direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise
self.position = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .position)
self.size = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .size)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(direction, forKey: .direction)
try container.encode(position, forKey: .position)
try container.encode(size, forKey: .size)
}
}

View File

@ -0,0 +1,49 @@
//
// FillShape.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
enum FillRule: Int, Codable {
case none
case nonZeroWinding
case evenOdd
}
/// An item that defines a fill render
final class Fill: ShapeItem {
/// The opacity of the fill
let opacity: KeyframeGroup<Vector1D>
/// The color keyframes for the fill
let color: KeyframeGroup<Color>
let fillRule: FillRule
private enum CodingKeys : String, CodingKey {
case opacity = "o"
case color = "c"
case fillRule = "r"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Fill.CodingKeys.self)
self.opacity = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .opacity)
self.color = try container.decode(KeyframeGroup<Color>.self, forKey: .color)
self.fillRule = try container.decodeIfPresent(FillRule.self, forKey: .fillRule) ?? .nonZeroWinding
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(opacity, forKey: .opacity)
try container.encode(color, forKey: .color)
try container.encode(fillRule, forKey: .fillRule)
}
}

View File

@ -0,0 +1,86 @@
//
// GradientFill.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
enum GradientType: Int, Codable {
case none
case linear
case radial
}
/// An item that define a gradient fill
final class GradientFill: ShapeItem {
/// The opacity of the fill
let opacity: KeyframeGroup<Vector1D>
/// The start of the gradient
let startPoint: KeyframeGroup<Vector3D>
/// The end of the gradient
let endPoint: KeyframeGroup<Vector3D>
/// The type of gradient
let gradientType: GradientType
/// Gradient Highlight Length. Only if type is Radial
let highlightLength: KeyframeGroup<Vector1D>?
/// Highlight Angle. Only if type is Radial
let highlightAngle: KeyframeGroup<Vector1D>?
/// The number of color points in the gradient
let numberOfColors: Int
/// The Colors of the gradient.
let colors: KeyframeGroup<[Double]>
private enum CodingKeys : String, CodingKey {
case opacity = "o"
case startPoint = "s"
case endPoint = "e"
case gradientType = "t"
case highlightLength = "h"
case highlightAngle = "a"
case colors = "g"
}
private enum GradientDataKeys : String, CodingKey {
case numberOfColors = "p"
case colors = "k"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: GradientFill.CodingKeys.self)
self.opacity = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .opacity)
self.startPoint = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .startPoint)
self.endPoint = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .endPoint)
self.gradientType = try container.decode(GradientType.self, forKey: .gradientType)
self.highlightLength = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .highlightLength)
self.highlightAngle = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .highlightAngle)
let colorsContainer = try container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
self.colors = try colorsContainer.decode(KeyframeGroup<[Double]>.self, forKey: .colors)
self.numberOfColors = try colorsContainer.decode(Int.self, forKey: .numberOfColors)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(opacity, forKey: .opacity)
try container.encode(startPoint, forKey: .startPoint)
try container.encode(endPoint, forKey: .endPoint)
try container.encode(gradientType, forKey: .gradientType)
try container.encodeIfPresent(highlightLength, forKey: .highlightLength)
try container.encodeIfPresent(highlightAngle, forKey: .highlightAngle)
var colorsContainer = container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
try colorsContainer.encode(numberOfColors, forKey: .numberOfColors)
try colorsContainer.encode(colors, forKey: .colors)
}
}

View File

@ -0,0 +1,125 @@
//
// GradientStroke.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
enum LineCap: Int, Codable {
case none
case butt
case round
case square
}
enum LineJoin: Int, Codable {
case none
case miter
case round
case bevel
}
/// An item that define an ellipse shape
final class GradientStroke: ShapeItem {
/// The opacity of the fill
let opacity: KeyframeGroup<Vector1D>
/// The start of the gradient
let startPoint: KeyframeGroup<Vector3D>
/// The end of the gradient
let endPoint: KeyframeGroup<Vector3D>
/// The type of gradient
let gradientType: GradientType
/// Gradient Highlight Length. Only if type is Radial
let highlightLength: KeyframeGroup<Vector1D>?
/// Highlight Angle. Only if type is Radial
let highlightAngle: KeyframeGroup<Vector1D>?
/// The number of color points in the gradient
let numberOfColors: Int
/// The Colors of the gradient.
let colors: KeyframeGroup<[Double]>
/// The width of the stroke
let width: KeyframeGroup<Vector1D>
/// Line Cap
let lineCap: LineCap
/// Line Join
let lineJoin: LineJoin
/// Miter Limit
let miterLimit: Double
/// The dash pattern of the stroke
let dashPattern: [DashElement]?
private enum CodingKeys : String, CodingKey {
case opacity = "o"
case startPoint = "s"
case endPoint = "e"
case gradientType = "t"
case highlightLength = "h"
case highlightAngle = "a"
case colors = "g"
case width = "w"
case lineCap = "lc"
case lineJoin = "lj"
case miterLimit = "ml"
case dashPattern = "d"
}
private enum GradientDataKeys : String, CodingKey {
case numberOfColors = "p"
case colors = "k"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: GradientStroke.CodingKeys.self)
self.opacity = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .opacity)
self.startPoint = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .startPoint)
self.endPoint = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .endPoint)
self.gradientType = try container.decode(GradientType.self, forKey: .gradientType)
self.highlightLength = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .highlightLength)
self.highlightAngle = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .highlightAngle)
self.width = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .width)
self.lineCap = try container.decodeIfPresent(LineCap.self, forKey: .lineCap) ?? .round
self.lineJoin = try container.decodeIfPresent(LineJoin.self, forKey: .lineJoin) ?? .round
self.miterLimit = try container.decodeIfPresent(Double.self, forKey: .miterLimit) ?? 4
// TODO Decode Color Objects instead of array.
let colorsContainer = try container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
self.colors = try colorsContainer.decode(KeyframeGroup<[Double]>.self, forKey: .colors)
self.numberOfColors = try colorsContainer.decode(Int.self, forKey: .numberOfColors)
self.dashPattern = try container.decodeIfPresent([DashElement].self, forKey: .dashPattern)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(opacity, forKey: .opacity)
try container.encode(startPoint, forKey: .startPoint)
try container.encode(endPoint, forKey: .endPoint)
try container.encode(gradientType, forKey: .gradientType)
try container.encodeIfPresent(highlightLength, forKey: .highlightLength)
try container.encodeIfPresent(highlightAngle, forKey: .highlightAngle)
try container.encode(width, forKey: .width)
try container.encode(lineCap, forKey: .lineCap)
try container.encode(lineJoin, forKey: .lineJoin)
try container.encode(miterLimit, forKey: .miterLimit)
var colorsContainer = container.nestedContainer(keyedBy: GradientDataKeys.self, forKey: .colors)
try colorsContainer.encode(numberOfColors, forKey: .numberOfColors)
try colorsContainer.encode(colors, forKey: .colors)
try container.encodeIfPresent(dashPattern, forKey: .dashPattern)
}
}

View File

@ -0,0 +1,32 @@
//
// GroupItem.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// An item that define an ellipse shape
final class Group: ShapeItem {
/// A list of shape items.
let items: [ShapeItem]
private enum CodingKeys : String, CodingKey {
case items = "it"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Group.CodingKeys.self)
self.items = try container.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .items)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(items, forKey: .items)
}
}

View File

@ -0,0 +1,41 @@
//
// Merge.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
enum MergeMode: Int, Codable {
case none
case merge
case add
case subtract
case intersect
case exclude
}
/// An item that define an ellipse shape
final class Merge: ShapeItem {
/// The mode of the merge path
let mode: MergeMode
private enum CodingKeys : String, CodingKey {
case mode = "mm"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Merge.CodingKeys.self)
self.mode = try container.decode(MergeMode.self, forKey: .mode)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(mode, forKey: .mode)
}
}

View File

@ -0,0 +1,50 @@
//
// Rectangle.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// An item that define an ellipse shape
final class Rectangle: ShapeItem {
/// The direction of the rect.
let direction: PathDirection
/// The position
let position: KeyframeGroup<Vector3D>
/// The size
let size: KeyframeGroup<Vector3D>
/// The Corner radius of the rectangle
let cornerRadius: KeyframeGroup<Vector1D>
private enum CodingKeys : String, CodingKey {
case direction = "d"
case position = "p"
case size = "s"
case cornerRadius = "r"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Rectangle.CodingKeys.self)
self.direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise
self.position = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .position)
self.size = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .size)
self.cornerRadius = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .cornerRadius)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(direction, forKey: .direction)
try container.encode(position, forKey: .position)
try container.encode(size, forKey: .size)
try container.encode(cornerRadius, forKey: .cornerRadius)
}
}

View File

@ -0,0 +1,80 @@
//
// Repeater.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// An item that define an ellipse shape
final class Repeater: ShapeItem {
/// The number of copies to repeat
let copies: KeyframeGroup<Vector1D>
/// The offset of each copy
let offset: KeyframeGroup<Vector1D>
/// Start Opacity
let startOpacity: KeyframeGroup<Vector1D>
/// End opacity
let endOpacity: KeyframeGroup<Vector1D>
/// The rotation
let rotation: KeyframeGroup<Vector1D>
/// Anchor Point
let anchorPoint: KeyframeGroup<Vector3D>
/// Position
let position: KeyframeGroup<Vector3D>
/// Scale
let scale: KeyframeGroup<Vector3D>
private enum CodingKeys : String, CodingKey {
case copies = "c"
case offset = "o"
case transform = "tr"
}
private enum TransformKeys : String, CodingKey {
case rotation = "r"
case startOpacity = "so"
case endOpacity = "eo"
case anchorPoint = "a"
case position = "p"
case scale = "s"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Repeater.CodingKeys.self)
self.copies = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .copies) ?? KeyframeGroup(Vector1D(0))
self.offset = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .offset) ?? KeyframeGroup(Vector1D(0))
let transformContainer = try container.nestedContainer(keyedBy: TransformKeys.self, forKey: .transform)
self.startOpacity = try transformContainer.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .startOpacity) ?? KeyframeGroup(Vector1D(100))
self.endOpacity = try transformContainer.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .endOpacity) ?? KeyframeGroup(Vector1D(100))
self.rotation = try transformContainer.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .rotation) ?? KeyframeGroup(Vector1D(0))
self.position = try transformContainer.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .position) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
self.anchorPoint = try transformContainer.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .anchorPoint) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
self.scale = try transformContainer.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .scale) ?? KeyframeGroup(Vector3D(x: Double(100), y: 100, z: 100))
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(copies, forKey: .copies)
try container.encode(offset, forKey: .offset)
var transformContainer = container.nestedContainer(keyedBy: TransformKeys.self, forKey: .transform)
try transformContainer.encode(startOpacity, forKey: .startOpacity)
try transformContainer.encode(endOpacity, forKey: .endOpacity)
try transformContainer.encode(rotation, forKey: .rotation)
try transformContainer.encode(position, forKey: .position)
try transformContainer.encode(anchorPoint, forKey: .anchorPoint)
try transformContainer.encode(scale, forKey: .scale)
}
}

View File

@ -0,0 +1,37 @@
//
// VectorShape.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// An item that define an ellipse shape
final class Shape: ShapeItem {
/// The Path
let path: KeyframeGroup<BezierPath>
let direction: PathDirection?
private enum CodingKeys : String, CodingKey {
case path = "ks"
case direction = "d"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Shape.CodingKeys.self)
self.path = try container.decode(KeyframeGroup<BezierPath>.self, forKey: .path)
self.direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(path, forKey: .path)
try container.encodeIfPresent(direction, forKey: .direction)
}
}

View File

@ -0,0 +1,95 @@
//
// ShapeItem.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// Used for mapping a heterogeneous list to classes for parsing.
extension ShapeType: ClassFamily {
static var discriminator: Discriminator = .type
func getType() -> AnyObject.Type {
switch self {
case .ellipse:
return Ellipse.self
case .fill:
return Fill.self
case .gradientFill:
return GradientFill.self
case .group:
return Group.self
case .gradientStroke:
return GradientStroke.self
case .merge:
return Merge.self
case .rectangle:
return Rectangle.self
case .repeater:
return Repeater.self
case .shape:
return Shape.self
case .star:
return Star.self
case .stroke:
return Stroke.self
case .trim:
return Trim.self
case .transform:
return ShapeTransform.self
default:
return ShapeItem.self
}
}
}
enum ShapeType: String, Codable {
case ellipse = "el"
case fill = "fl"
case gradientFill = "gf"
case group = "gr"
case gradientStroke = "gs"
case merge = "mm"
case rectangle = "rc"
case repeater = "rp"
case round = "rd"
case shape = "sh"
case star = "sr"
case stroke = "st"
case trim = "tm"
case transform = "tr"
case unknown
public init(from decoder: Decoder) throws {
self = try ShapeType(rawValue: decoder.singleValueContainer().decode(RawValue.self)) ?? .unknown
}
}
/// An item belonging to a Shape Layer
class ShapeItem: Codable {
/// The name of the shape
let name: String
/// The type of shape
let type: ShapeType
let hidden: Bool
private enum CodingKeys : String, CodingKey {
case name = "nm"
case type = "ty"
case hidden = "hd"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ShapeItem.CodingKeys.self)
self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Layer"
self.type = try container.decode(ShapeType.self, forKey: .type)
self.hidden = try container.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
}
}

View File

@ -0,0 +1,68 @@
//
// TransformItem.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// An item that define an ellipse shape
final class ShapeTransform: ShapeItem {
/// Anchor Point
let anchor: KeyframeGroup<Vector3D>
/// Position
let position: KeyframeGroup<Vector3D>
/// Scale
let scale: KeyframeGroup<Vector3D>
/// Rotation
let rotation: KeyframeGroup<Vector1D>
/// opacity
let opacity: KeyframeGroup<Vector1D>
/// Skew
let skew: KeyframeGroup<Vector1D>
/// Skew Axis
let skewAxis: KeyframeGroup<Vector1D>
private enum CodingKeys : String, CodingKey {
case anchor = "a"
case position = "p"
case scale = "s"
case rotation = "r"
case opacity = "o"
case skew = "sk"
case skewAxis = "sa"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ShapeTransform.CodingKeys.self)
self.anchor = try container.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .anchor) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
self.position = try container.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .position) ?? KeyframeGroup(Vector3D(x: Double(0), y: 0, z: 0))
self.scale = try container.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .scale) ?? KeyframeGroup(Vector3D(x: Double(100), y: 100, z: 100))
self.rotation = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .rotation) ?? KeyframeGroup(Vector1D(0))
self.opacity = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .opacity) ?? KeyframeGroup(Vector1D(100))
self.skew = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .skew) ?? KeyframeGroup(Vector1D(0))
self.skewAxis = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .skewAxis) ?? KeyframeGroup(Vector1D(0))
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(anchor, forKey: .anchor)
try container.encode(position, forKey: .position)
try container.encode(scale, forKey: .scale)
try container.encode(rotation, forKey: .rotation)
try container.encode(opacity, forKey: .opacity)
try container.encode(skew, forKey: .skew)
try container.encode(skewAxis, forKey: .skewAxis)
}
}

View File

@ -0,0 +1,86 @@
//
// Star.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
enum StarType: Int, Codable {
case none
case star
case polygon
}
/// An item that define an ellipse shape
final class Star: ShapeItem {
/// The direction of the star.
let direction: PathDirection
/// The position of the star
let position: KeyframeGroup<Vector3D>
/// The outer radius of the star
let outerRadius: KeyframeGroup<Vector1D>
/// The outer roundness of the star
let outerRoundness: KeyframeGroup<Vector1D>
/// The outer radius of the star
let innerRadius: KeyframeGroup<Vector1D>?
/// The outer roundness of the star
let innerRoundness: KeyframeGroup<Vector1D>?
/// The rotation of the star
let rotation: KeyframeGroup<Vector1D>
/// The number of points on the star
let points: KeyframeGroup<Vector1D>
/// The type of star
let starType: StarType
private enum CodingKeys : String, CodingKey {
case direction = "d"
case position = "p"
case outerRadius = "or"
case outerRoundness = "os"
case innerRadius = "ir"
case innerRoundness = "is"
case rotation = "r"
case points = "pt"
case starType = "sy"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Star.CodingKeys.self)
self.direction = try container.decodeIfPresent(PathDirection.self, forKey: .direction) ?? .clockwise
self.position = try container.decode(KeyframeGroup<Vector3D>.self, forKey: .position)
self.outerRadius = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .outerRadius)
self.outerRoundness = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .outerRoundness)
self.innerRadius = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .innerRadius)
self.innerRoundness = try container.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .innerRoundness)
self.rotation = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .rotation)
self.points = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .points)
self.starType = try container.decode(StarType.self, forKey: .starType)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(direction, forKey: .direction)
try container.encode(position, forKey: .position)
try container.encode(outerRadius, forKey: .outerRadius)
try container.encode(outerRoundness, forKey: .outerRoundness)
try container.encode(innerRadius, forKey: .innerRadius)
try container.encode(innerRoundness, forKey: .innerRoundness)
try container.encode(rotation, forKey: .rotation)
try container.encode(points, forKey: .points)
try container.encode(starType, forKey: .starType)
}
}

View File

@ -0,0 +1,67 @@
//
// Stroke.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
/// An item that define an ellipse shape
final class Stroke: ShapeItem {
/// The opacity of the stroke
let opacity: KeyframeGroup<Vector1D>
/// The Color of the stroke
let color: KeyframeGroup<Color>
/// The width of the stroke
let width: KeyframeGroup<Vector1D>
/// Line Cap
let lineCap: LineCap
/// Line Join
let lineJoin: LineJoin
/// Miter Limit
let miterLimit: Double
/// The dash pattern of the stroke
let dashPattern: [DashElement]?
private enum CodingKeys : String, CodingKey {
case opacity = "o"
case color = "c"
case width = "w"
case lineCap = "lc"
case lineJoin = "lj"
case miterLimit = "ml"
case dashPattern = "d"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Stroke.CodingKeys.self)
self.opacity = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .opacity)
self.color = try container.decode(KeyframeGroup<Color>.self, forKey: .color)
self.width = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .width)
self.lineCap = try container.decodeIfPresent(LineCap.self, forKey: .lineCap) ?? .round
self.lineJoin = try container.decodeIfPresent(LineJoin.self, forKey: .lineJoin) ?? .round
self.miterLimit = try container.decodeIfPresent(Double.self, forKey: .miterLimit) ?? 4
self.dashPattern = try container.decodeIfPresent([DashElement].self, forKey: .dashPattern)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(opacity, forKey: .opacity)
try container.encode(color, forKey: .color)
try container.encode(width, forKey: .width)
try container.encode(lineCap, forKey: .lineCap)
try container.encode(lineJoin, forKey: .lineJoin)
try container.encode(miterLimit, forKey: .miterLimit)
try container.encodeIfPresent(dashPattern, forKey: .dashPattern)
}
}

View File

@ -0,0 +1,53 @@
//
// Trim.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/8/19.
//
import Foundation
enum TrimType: Int, Codable {
case simultaneously = 1
case individually = 2
}
/// An item that define an ellipse shape
final class Trim: ShapeItem {
/// The start of the trim
let start: KeyframeGroup<Vector1D>
/// The end of the trim
let end: KeyframeGroup<Vector1D>
/// The offset of the trim
let offset: KeyframeGroup<Vector1D>
let trimType: TrimType
private enum CodingKeys : String, CodingKey {
case start = "s"
case end = "e"
case offset = "o"
case trimType = "m"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Trim.CodingKeys.self)
self.start = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .start)
self.end = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .end)
self.offset = try container.decode(KeyframeGroup<Vector1D>.self, forKey: .offset)
self.trimType = try container.decode(TrimType.self, forKey: .trimType)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(start, forKey: .start)
try container.encode(end, forKey: .end)
try container.encode(offset, forKey: .offset)
try container.encode(trimType, forKey: .trimType)
}
}

View File

@ -0,0 +1,35 @@
//
// Font.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/9/19.
//
import Foundation
final class Font: Codable {
let name: String
let familyName: String
let style: String
let ascent: Double
private enum CodingKeys: String, CodingKey {
case name = "fName"
case familyName = "fFamily"
case style = "fStyle"
case ascent = "ascent"
}
}
/// A list of fonts
final class FontList: Codable {
let fonts: [Font]
enum CodingKeys : String, CodingKey {
case fonts = "list"
}
}

View File

@ -0,0 +1,72 @@
//
// Glyph.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/9/19.
//
import Foundation
/// A model that holds a vector character
final class Glyph: Codable {
/// The character
let character: String
/// The font size of the character
let fontSize: Double
/// The font family of the character
let fontFamily: String
/// The Style of the character
let fontStyle: String
/// The Width of the character
let width: Double
/// The Shape Data of the Character
let shapes: [ShapeItem]
private enum CodingKeys: String, CodingKey {
case character = "ch"
case fontSize = "size"
case fontFamily = "fFamily"
case fontStyle = "style"
case width = "w"
case shapeWrapper = "data"
}
private enum ShapeKey: String, CodingKey {
case shapes = "shapes"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Glyph.CodingKeys.self)
self.character = try container.decode(String.self, forKey: .character)
self.fontSize = try container.decode(Double.self, forKey: .fontSize)
self.fontFamily = try container.decode(String.self, forKey: .fontFamily)
self.fontStyle = try container.decode(String.self, forKey: .fontStyle)
self.width = try container.decode(Double.self, forKey: .width)
if container.contains(.shapeWrapper),
let shapeContainer = try? container.nestedContainer(keyedBy: ShapeKey.self, forKey: .shapeWrapper),
shapeContainer.contains(.shapes) {
self.shapes = try shapeContainer.decode([ShapeItem].self, ofFamily: ShapeType.self, forKey: .shapes)
} else {
self.shapes = []
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(character, forKey: .character)
try container.encode(fontSize, forKey: .fontSize)
try container.encode(fontFamily, forKey: .fontFamily)
try container.encode(fontStyle, forKey: .fontStyle)
try container.encode(width, forKey: .width)
var shapeContainer = container.nestedContainer(keyedBy: ShapeKey.self, forKey: .shapeWrapper)
try shapeContainer.encode(shapes, forKey: .shapes)
}
}

View File

@ -0,0 +1,99 @@
//
// TextAnimator.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/9/19.
//
import Foundation
final class TextAnimator: Codable {
let name: String
/// Anchor
let anchor: KeyframeGroup<Vector3D>?
/// Position
let position: KeyframeGroup<Vector3D>?
/// Scale
let scale: KeyframeGroup<Vector3D>?
/// Skew
let skew: KeyframeGroup<Vector1D>?
/// Skew Axis
let skewAxis: KeyframeGroup<Vector1D>?
/// Rotation
let rotation: KeyframeGroup<Vector1D>?
/// Opacity
let opacity: KeyframeGroup<Vector1D>?
/// Stroke Color
let strokeColor: KeyframeGroup<Color>?
/// Fill Color
let fillColor: KeyframeGroup<Color>?
/// Stroke Width
let strokeWidth: KeyframeGroup<Vector1D>?
/// Tracking
let tracking: KeyframeGroup<Vector1D>?
private enum CodingKeys: String, CodingKey {
// case textSelector = "s" TODO
case textAnimator = "a"
case name = "nm"
}
private enum TextSelectorKeys: String, CodingKey {
case start = "s"
case end = "e"
case offset = "o"
}
private enum TextAnimatorKeys: String, CodingKey {
case fillColor = "fc"
case strokeColor = "sc"
case strokeWidth = "sw"
case tracking = "t"
case anchor = "a"
case position = "p"
case scale = "s"
case skew = "sk"
case skewAxis = "sa"
case rotation = "r"
case opacity = "o"
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: TextAnimator.CodingKeys.self)
self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? ""
let animatorContainer = try container.nestedContainer(keyedBy: TextAnimatorKeys.self, forKey: .textAnimator)
self.fillColor = try animatorContainer.decodeIfPresent(KeyframeGroup<Color>.self, forKey: .fillColor)
self.strokeColor = try animatorContainer.decodeIfPresent(KeyframeGroup<Color>.self, forKey: .strokeColor)
self.strokeWidth = try animatorContainer.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .strokeWidth)
self.tracking = try animatorContainer.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .tracking)
self.anchor = try animatorContainer.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .anchor)
self.position = try animatorContainer.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .position)
self.scale = try animatorContainer.decodeIfPresent(KeyframeGroup<Vector3D>.self, forKey: .scale)
self.skew = try animatorContainer.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .skew)
self.skewAxis = try animatorContainer.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .skewAxis)
self.rotation = try animatorContainer.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .rotation)
self.opacity = try animatorContainer.decodeIfPresent(KeyframeGroup<Vector1D>.self, forKey: .opacity)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
var animatorContainer = container.nestedContainer(keyedBy: TextAnimatorKeys.self, forKey: .textAnimator)
try animatorContainer.encodeIfPresent(fillColor, forKey: .fillColor)
try animatorContainer.encodeIfPresent(strokeColor, forKey: .strokeColor)
try animatorContainer.encodeIfPresent(strokeWidth, forKey: .strokeWidth)
try animatorContainer.encodeIfPresent(tracking, forKey: .tracking)
}
}

View File

@ -0,0 +1,70 @@
//
// TextDocument.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/9/19.
//
import Foundation
enum TextJustification: Int, Codable {
case left
case right
case center
}
final class TextDocument: Codable {
/// The Text
let text: String
/// The Font size
let fontSize: Double
/// The Font Family
let fontFamily: String
/// Justification
let justification: TextJustification
/// Tracking
let tracking: Int
/// Line Height
let lineHeight: Double
/// Baseline
let baseline: Double?
/// Fill Color data
let fillColorData: Color?
/// Scroke Color data
let strokeColorData: Color?
/// Stroke Width
let strokeWidth: Double?
/// Stroke Over Fill
let strokeOverFill: Bool?
let textFramePosition: Vector3D?
let textFrameSize: Vector3D?
private enum CodingKeys : String, CodingKey {
case text = "t"
case fontSize = "s"
case fontFamily = "f"
case justification = "j"
case tracking = "tr"
case lineHeight = "lh"
case baseline = "ls"
case fillColorData = "fc"
case strokeColorData = "sc"
case strokeWidth = "sw"
case strokeOverFill = "of"
case textFramePosition = "ps"
case textFrameSize = "sz"
}
}

View File

@ -0,0 +1,95 @@
//
// ItemsExtension.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/18/19.
//
import Foundation
final class NodeTree {
var rootNode: AnimatorNode? = nil
var transform: ShapeTransform? = nil
var renderContainers: [ShapeContainerLayer] = []
var paths: [PathOutputNode] = []
var childrenNodes: [AnimatorNode] = []
}
extension Array where Element == ShapeItem {
func initializeNodeTree() -> NodeTree {
let nodeTree = NodeTree()
for item in self {
guard item.hidden == false, item.type != .unknown else { continue }
if let fill = item as? Fill {
let node = FillNode(parentNode: nodeTree.rootNode, fill: fill)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
} else if let stroke = item as? Stroke {
let node = StrokeNode(parentNode: nodeTree.rootNode, stroke: stroke)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
} else if let gradientFill = item as? GradientFill {
let node = GradientFillNode(parentNode: nodeTree.rootNode, gradientFill: gradientFill)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
} else if let gradientStroke = item as? GradientStroke {
let node = GradientStrokeNode(parentNode: nodeTree.rootNode, gradientStroke: gradientStroke)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
} else if let ellipse = item as? Ellipse {
let node = EllipseNode(parentNode: nodeTree.rootNode, ellipse: ellipse)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
} else if let rect = item as? Rectangle {
let node = RectangleNode(parentNode: nodeTree.rootNode, rectangle: rect)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
} else if let star = item as? Star {
switch star.starType {
case .none:
continue
case .polygon:
let node = PolygonNode(parentNode: nodeTree.rootNode, star: star)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
case .star:
let node = StarNode(parentNode: nodeTree.rootNode, star: star)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
}
} else if let shape = item as? Shape {
let node = ShapeNode(parentNode: nodeTree.rootNode, shape: shape)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
} else if let trim = item as? Trim {
let node = TrimPathNode(parentNode: nodeTree.rootNode, trim: trim, upstreamPaths: nodeTree.paths)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
} else if let xform = item as? ShapeTransform {
nodeTree.transform = xform
continue
} else if let group = item as? Group {
let tree = group.items.initializeNodeTree()
let node = GroupNode(name: group.name, parentNode: nodeTree.rootNode, tree: tree)
nodeTree.rootNode = node
nodeTree.childrenNodes.append(node)
/// Now add all child paths to current tree
nodeTree.paths.append(contentsOf: tree.paths)
nodeTree.renderContainers.append(node.container)
}
if let pathNode = nodeTree.rootNode as? PathNode {
//// Add path container to the node tree
nodeTree.paths.append(pathNode.pathOutput)
}
if let renderNode = nodeTree.rootNode as? RenderNode {
nodeTree.renderContainers.append(ShapeRenderLayer(renderer: renderNode.renderer))
}
}
return nodeTree
}
}

View File

@ -0,0 +1,47 @@
//
// NodeProperty.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import CoreGraphics
/// A node property that holds a reference to a T ValueProvider and a T ValueContainer.
class NodeProperty<T>: AnyNodeProperty {
var valueType: Any.Type { return T.self }
var value: T {
return typedContainer.outputValue
}
var valueContainer: AnyValueContainer {
return typedContainer
}
var valueProvider: AnyValueProvider
init(provider: AnyValueProvider) {
self.valueProvider = provider
self.typedContainer = ValueContainer<T>(provider.value(frame: 0) as! T)
self.typedContainer.setNeedsUpdate()
}
func needsUpdate(frame: CGFloat) -> Bool {
return valueContainer.needsUpdate || valueProvider.hasUpdate(frame: frame)
}
func setProvider(provider: AnyValueProvider) {
guard provider.valueType == valueType else { return }
self.valueProvider = provider
valueContainer.setNeedsUpdate()
}
func update(frame: CGFloat) {
typedContainer.setValue(valueProvider.value(frame: frame), forFrame: frame)
}
fileprivate var typedContainer: ValueContainer<T>
}

View File

@ -0,0 +1,44 @@
//
// AnyNodeProperty.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import CoreGraphics
/// A property of a node. The node property holds a provider and a container
protocol AnyNodeProperty {
/// Returns true if the property needs to recompute its stored value
func needsUpdate(frame: CGFloat) -> Bool
/// Updates the property for the frame
func update(frame: CGFloat)
/// The stored value container for the property
var valueContainer: AnyValueContainer { get }
/// The value provider for the property
var valueProvider: AnyValueProvider { get }
/// The Type of the value provider
var valueType: Any.Type { get }
/// Sets the value provider for the property.
func setProvider(provider: AnyValueProvider)
}
extension AnyNodeProperty {
/// Returns the most recently computed value for the keypath, returns nil if property wasn't found
func getValueOfType<T>() -> T? {
return valueContainer.value as? T
}
/// Returns the most recently computed value for the keypath, returns nil if property wasn't found
func getValue() -> Any? {
return valueContainer.value
}
}

View File

@ -0,0 +1,26 @@
//
// AnyValueContainer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import CoreGraphics
/// The container for the value of a property.
protocol AnyValueContainer: class {
/// The stored value of the container
var value: Any { get }
/// Notifies the provider that it should update its container
func setNeedsUpdate()
/// When true the container needs to have its value updated by its provider
var needsUpdate: Bool { get }
/// The frame time of the last provided update
var lastUpdateFrame: CGFloat { get }
}

View File

@ -0,0 +1,24 @@
//
// KeypathSettable.swift
// lottie-swift
//
// Created by Brandon Withrow on 2/4/19.
//
import Foundation
import QuartzCore
/// Protocol that provides keypath search functionality. Returns all node properties associated with a keypath.
protocol KeypathSearchable {
/// The name of the Keypath
var keypathName: String { get }
/// A list of properties belonging to the keypath.
var keypathProperties: [String : AnyNodeProperty] { get }
/// Children Keypaths
var childKeypaths: [KeypathSearchable] { get }
var keypathLayer: CALayer? { get }
}

View File

@ -0,0 +1,42 @@
//
// NodePropertyMap.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/21/19.
//
import Foundation
import QuartzCore
protocol NodePropertyMap {
var properties: [AnyNodeProperty] { get }
}
extension NodePropertyMap {
var childKeypaths: [KeypathSearchable] {
return []
}
var keypathLayer: CALayer? {
return nil
}
/// Checks if the node's local contents need to be rebuilt.
func needsLocalUpdate(frame: CGFloat) -> Bool {
for property in properties {
if property.needsUpdate(frame: frame) {
return true
}
}
return false
}
/// Rebuilds only the local nodes that have an update for the frame
func updateNodeProperties(frame: CGFloat) {
properties.forEach { (property) in
property.update(frame: frame)
}
}
}

View File

@ -0,0 +1,43 @@
//
// ValueContainer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import CoreGraphics
/// A container for a node value that is Typed to T.
class ValueContainer<T>: AnyValueContainer {
private(set) var lastUpdateFrame: CGFloat = CGFloat.infinity
func setValue(_ value: Any, forFrame: CGFloat) {
if let typedValue = value as? T {
needsUpdate = false
lastUpdateFrame = forFrame
outputValue = typedValue
}
}
func setNeedsUpdate() {
needsUpdate = true
}
var value: Any {
return outputValue as Any
}
var outputValue: T {
didSet {
needsUpdate = false
}
}
init(_ value: T) {
self.outputValue = value
}
fileprivate(set) var needsUpdate: Bool = true
}

View File

@ -0,0 +1,33 @@
//
// KeyframeGroupInterpolator.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/22/19.
//
import Foundation
import CoreGraphics
/// A value provider that produces an array of values from an array of Keyframe Interpolators
final class GroupInterpolator<ValueType>: AnyValueProvider where ValueType: Interpolatable {
var valueType: Any.Type {
return [ValueType].self
}
func hasUpdate(frame: CGFloat) -> Bool {
let updated = keyframeInterpolators.first(where: {$0.hasUpdate(frame: frame)})
return updated != nil
}
func value(frame: CGFloat) -> Any {
let output = keyframeInterpolators.map({$0.value(frame: frame) as! ValueType})
return output
}
/// Initialize with an array of array of keyframes.
init(keyframeGroups: ContiguousArray<ContiguousArray<Keyframe<ValueType>>>) {
self.keyframeInterpolators = ContiguousArray(keyframeGroups.map({KeyframeInterpolator(keyframes: $0)}))
}
let keyframeInterpolators: ContiguousArray<KeyframeInterpolator<ValueType>>
}

View File

@ -0,0 +1,233 @@
//
// KeyframeInterpolator.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/15/19.
//
import Foundation
import CoreGraphics
/// A value provider that produces a value at Time from a group of keyframes
final class KeyframeInterpolator<ValueType>: AnyValueProvider where ValueType: Interpolatable {
init(keyframes: ContiguousArray<Keyframe<ValueType>>) {
self.keyframes = keyframes
}
let keyframes: ContiguousArray<Keyframe<ValueType>>
var valueType: Any.Type {
return ValueType.self
}
/**
Returns true to trigger a frame update for this interpolator.
An interpolator will be asked if it needs to update every frame.
If the interpolator needs updating it will be asked to compute its value for
the given frame.
Cases a keyframe should not be updated:
- If time is in span and leading keyframe is hold
- If time is after the last keyframe.
- If time is before the first keyframe
Cases for updating a keyframe:
- If time is in the span, and is not a hold
- If time is outside of the span, and there are more keyframes
- If a value delegate is set
- If leading and trailing are both nil.
*/
func hasUpdate(frame: CGFloat) -> Bool {
if lastUpdatedFrame == nil {
return true
}
if let leading = leadingKeyframe,
trailingKeyframe == nil,
leading.time < frame {
/// Frame is after bounds of keyframes
return false
}
if let trailing = trailingKeyframe,
leadingKeyframe == nil,
frame < trailing.time {
/// Frame is before bounds of keyframes
return false
}
if let leading = leadingKeyframe,
let trailing = trailingKeyframe,
leading.isHold,
leading.time < frame,
frame < trailing.time {
return false
}
return true
}
fileprivate var lastUpdatedFrame: CGFloat?
@discardableResult
func value(frame: CGFloat) -> Any {
// First set the keyframe span for the frame.
updateSpanIndices(frame: frame)
lastUpdatedFrame = frame
// If only one keyframe return its value
let progress: CGFloat
let value: ValueType
if let leading = leadingKeyframe,
let trailing = trailingKeyframe {
/// We have leading and trailing keyframe.
progress = leading.interpolatedProgress(trailing, keyTime: frame)
value = leading.interpolate(trailing, progress: progress)
} else if let leading = leadingKeyframe {
progress = 0
value = leading.value
} else if let trailing = trailingKeyframe {
progress = 1
value = trailing.value
} else {
/// Satisfy the compiler.
progress = 0
value = keyframes[0].value
}
return value
}
fileprivate var leadingIndex: Int? = nil
fileprivate var trailingIndex: Int? = nil
fileprivate var leadingKeyframe: Keyframe<ValueType>? = nil
fileprivate var trailingKeyframe: Keyframe<ValueType>? = nil
/// Finds the appropriate Leading and Trailing keyframe index for the given time.
fileprivate func updateSpanIndices(frame: CGFloat) {
guard keyframes.count > 0 else {
leadingIndex = nil
trailingIndex = nil
leadingKeyframe = nil
trailingKeyframe = nil
return
}
/**
This function searches through the array to find the span of two keyframes
that contain the current time.
We could use Array.first(where:) but that would search through the entire array
each frame.
Instead we track the last used index and search either forwards or
backwards from there. This reduces the iterations and complexity from
O(n), where n is the length of the sequence to
O(n), where n is the number of items after or before the last used index.
*/
if keyframes.count == 1 {
/// Only one keyframe. Set it as first and move on.
leadingIndex = 0
trailingIndex = nil
leadingKeyframe = keyframes[0]
trailingKeyframe = nil
return
}
/// Sets the initial keyframes. This is often only needed for the first check.
if leadingIndex == nil &&
trailingIndex == nil {
if frame < keyframes[0].time {
/// Time is before the first keyframe. Set it as the trailing.
trailingIndex = 0
} else {
/// Time is after the first keyframe. Set the keyframe and the trailing.
leadingIndex = 0
trailingIndex = 1
}
}
if let currentTrailing = trailingIndex,
keyframes[currentTrailing].time <= frame {
/// Time is after the current span. Iterate forward.
var newLeading = currentTrailing
var keyframeFound: Bool = false
while !keyframeFound {
leadingIndex = newLeading
trailingIndex = keyframes.validIndex(newLeading + 1)
guard let trailing = trailingIndex else {
/// We have reached the end of our keyframes. Time is after the last keyframe.
keyframeFound = true
continue
}
if frame < keyframes[trailing].time {
/// Keyframe in current span.
keyframeFound = true
continue
}
/// Advance the array.
newLeading = trailing
}
} else if let currentLeading = leadingIndex,
frame < keyframes[currentLeading].time {
/// Time is before the current span. Iterate backwards
var newTrailing = currentLeading
var keyframeFound: Bool = false
while !keyframeFound {
leadingIndex = keyframes.validIndex(newTrailing - 1)
trailingIndex = newTrailing
guard let leading = leadingIndex else {
/// We have reached the end of our keyframes. Time is after the last keyframe.
keyframeFound = true
continue
}
if keyframes[leading].time <= frame {
/// Keyframe in current span.
keyframeFound = true
continue
}
/// Step back
newTrailing = leading
}
}
if let keyFrame = leadingIndex {
leadingKeyframe = keyframes[keyFrame]
} else {
leadingKeyframe = nil
}
if let keyFrame = trailingIndex {
trailingKeyframe = keyframes[keyFrame]
} else {
trailingKeyframe = nil
}
}
}
fileprivate extension Array {
func validIndex(_ index: Int) -> Int? {
if 0 <= index, index < endIndex {
return index
}
return nil
}
}
fileprivate extension ContiguousArray {
func validIndex(_ index: Int) -> Int? {
if 0 <= index, index < endIndex {
return index
}
return nil
}
}

View File

@ -0,0 +1,38 @@
//
// SingleValueProvider.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import QuartzCore
/// Returns a value for every frame.
final class SingleValueProvider<ValueType>: AnyValueProvider {
var value: ValueType {
didSet {
hasUpdate = true
}
}
init(_ value: ValueType) {
self.value = value
}
var valueType: Any.Type {
return ValueType.self
}
func hasUpdate(frame: CGFloat) -> Bool {
return hasUpdate
}
func value(frame: CGFloat) -> Any {
hasUpdate = false
return value
}
private var hasUpdate: Bool = true
}

View File

@ -0,0 +1,247 @@
//
// TrimPathNode.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/23/19.
//
import Foundation
import QuartzCore
final class TrimPathProperties: NodePropertyMap, KeypathSearchable {
init(trim: Trim) {
self.keypathName = trim.name
self.start = NodeProperty(provider: KeyframeInterpolator(keyframes: trim.start.keyframes))
self.end = NodeProperty(provider: KeyframeInterpolator(keyframes: trim.end.keyframes))
self.offset = NodeProperty(provider: KeyframeInterpolator(keyframes: trim.offset.keyframes))
self.type = trim.trimType
self.keypathProperties = [
"Start" : start,
"End" : end,
"Offset" : offset
]
self.properties = Array(keypathProperties.values)
}
let keypathProperties: [String : AnyNodeProperty]
let properties: [AnyNodeProperty]
let keypathName: String
let start: NodeProperty<Vector1D>
let end: NodeProperty<Vector1D>
let offset: NodeProperty<Vector1D>
let type: TrimType
}
final class TrimPathNode: AnimatorNode {
let properties: TrimPathProperties
fileprivate let upstreamPaths: [PathOutputNode]
init(parentNode: AnimatorNode?, trim: Trim, upstreamPaths: [PathOutputNode]) {
self.outputNode = PassThroughOutputNode(parent: parentNode?.outputNode)
self.parentNode = parentNode
self.properties = TrimPathProperties(trim: trim)
self.upstreamPaths = upstreamPaths
}
// MARK: Animator Node
var propertyMap: NodePropertyMap & KeypathSearchable {
return properties
}
let parentNode: AnimatorNode?
let outputNode: NodeOutput
var hasLocalUpdates: Bool = false
var hasUpstreamUpdates: Bool = false
var lastUpdateFrame: CGFloat? = nil
var isEnabled: Bool = true
func forceUpstreamOutputUpdates() -> Bool {
return hasLocalUpdates || hasUpstreamUpdates
}
func rebuildOutputs(frame: CGFloat) {
/// Make sure there is a trim.
let startValue = properties.start.value.cgFloatValue * 0.01
let endValue = properties.end.value.cgFloatValue * 0.01
let start = min(startValue, endValue)
let end = max(startValue, endValue)
let offset = properties.offset.value.cgFloatValue.truncatingRemainder(dividingBy: 360) / 360
/// No need to trim, it's a full path
if start == 0, end == 1 {
return
}
/// All paths are empty.
if start == end {
for pathContainer in upstreamPaths {
pathContainer.removePaths(updateFrame: frame)
}
return
}
if properties.type == .simultaneously {
/// Just trim each path
for pathContainer in upstreamPaths {
let pathObjects = pathContainer.removePaths(updateFrame: frame)
for path in pathObjects {
// We are treating each compount path as an individual path. Its subpaths are treated as a whole.
pathContainer.appendPath(path.trim(fromPosition: start, toPosition: end, offset: offset, trimSimultaneously: false), updateFrame: frame)
}
}
return
}
/// Individual path trimming.
/// Brace yourself for the below code.
/// Normalize lengths with offset.
var startPosition = (start+offset).truncatingRemainder(dividingBy: 1)
var endPosition = (end+offset).truncatingRemainder(dividingBy: 1)
if startPosition < 0 {
startPosition = 1 + startPosition
}
if endPosition < 0 {
endPosition = 1 + endPosition
}
if startPosition == 1 {
startPosition = 0
}
if endPosition == 0 {
endPosition = 1
}
/// First get the total length of all paths.
var totalLength: CGFloat = 0
upstreamPaths.forEach({ totalLength = totalLength + $0.totalLength })
/// Now determine the start and end cut lengths
let startLength = startPosition * totalLength
let endLength = endPosition * totalLength
var pathStart: CGFloat = 0
/// Now loop through all path containers
for pathContainer in upstreamPaths {
let pathEnd = pathStart + pathContainer.totalLength
if !startLength.isInRange(pathStart, pathEnd) &&
endLength.isInRange(pathStart, pathEnd) {
// pathStart|=======E----------------------|pathEnd
// Cut path components, removing after end.
let pathCutLength = endLength - pathStart
let subpaths = pathContainer.removePaths(updateFrame: frame)
var subpathStart: CGFloat = 0
for path in subpaths {
let subpathEnd = subpathStart + path.length
if pathCutLength < subpathEnd {
/// This is the subpath that needs to be cut.
let cutLength = pathCutLength - subpathStart
let newPath = path.trim(fromPosition: 0, toPosition: cutLength / path.length, offset: 0, trimSimultaneously: false)
pathContainer.appendPath(newPath, updateFrame: frame)
break
} else {
/// Add to container and move on
pathContainer.appendPath(path, updateFrame: frame)
}
if pathCutLength == subpathEnd {
/// Right on the end. The next subpath is not included. Break.
break
}
subpathStart = subpathEnd
}
} else if !endLength.isInRange(pathStart, pathEnd) &&
startLength.isInRange(pathStart, pathEnd) {
// pathStart|-------S======================|pathEnd
//
// Cut path components, removing before beginning.
let pathCutLength = startLength - pathStart
// Clear paths from container
let subpaths = pathContainer.removePaths(updateFrame: frame)
var subpathStart: CGFloat = 0
for path in subpaths {
let subpathEnd = subpathStart + path.length
if subpathStart < pathCutLength, pathCutLength < subpathEnd {
/// This is the subpath that needs to be cut.
let cutLength = pathCutLength - subpathStart
let newPath = path.trim(fromPosition: cutLength / path.length, toPosition: 1, offset: 0, trimSimultaneously: false)
pathContainer.appendPath(newPath, updateFrame: frame)
} else if pathCutLength <= subpathStart {
pathContainer.appendPath(path, updateFrame: frame)
}
subpathStart = subpathEnd
}
} else if endLength.isInRange(pathStart, pathEnd) &&
startLength.isInRange(pathStart, pathEnd) {
// pathStart|-------S============E---------|endLength
// pathStart|=====E----------------S=======|endLength
// trim from path beginning to endLength.
// Cut path components, removing before beginnings.
let startCutLength = startLength - pathStart
let endCutLength = endLength - pathStart
// Clear paths from container
let subpaths = pathContainer.removePaths(updateFrame: frame)
var subpathStart: CGFloat = 0
for path in subpaths {
let subpathEnd = subpathStart + path.length
if !startCutLength.isInRange(subpathStart, subpathEnd) &&
!endCutLength.isInRange(subpathStart, subpathEnd) {
// The whole path is included. Add
// S|==============================|E
pathContainer.appendPath(path, updateFrame: frame)
} else if startCutLength.isInRange(subpathStart, subpathEnd) &&
!endCutLength.isInRange(subpathStart, subpathEnd) {
/// The start of the path needs to be trimmed
// |-------S======================|E
let cutLength = startCutLength - subpathStart
let newPath = path.trim(fromPosition: cutLength / path.length, toPosition: 1, offset: 0, trimSimultaneously: false)
pathContainer.appendPath(newPath, updateFrame: frame)
} else if !startCutLength.isInRange(subpathStart, subpathEnd) &&
endCutLength.isInRange(subpathStart, subpathEnd) {
// S|=======E----------------------|
let cutLength = endCutLength - subpathStart
let newPath = path.trim(fromPosition: 0, toPosition: cutLength / path.length, offset: 0, trimSimultaneously: false)
pathContainer.appendPath(newPath, updateFrame: frame)
break
} else if startCutLength.isInRange(subpathStart, subpathEnd) &&
endCutLength.isInRange(subpathStart, subpathEnd) {
// |-------S============E---------|
let cutFromLength = startCutLength - subpathStart
let cutToLength = endCutLength - subpathStart
let newPath = path.trim(fromPosition: cutFromLength / path.length, toPosition: cutToLength / path.length, offset: 0, trimSimultaneously: false)
pathContainer.appendPath(newPath, updateFrame: frame)
break
}
subpathStart = subpathEnd
}
} else if (endLength <= pathStart && pathEnd <= startLength) ||
(startLength <= pathStart && endLength <= pathStart) ||
(pathEnd <= startLength && pathEnd <= endLength) {
/// The Path needs to be cleared
pathContainer.removePaths(updateFrame: frame)
}
pathStart = pathEnd
}
}
}

View File

@ -0,0 +1,70 @@
//
// TransformNodeOutput.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import CoreGraphics
import QuartzCore
class GroupOutputNode: NodeOutput {
init(parent: NodeOutput?, rootNode: NodeOutput?) {
self.parent = parent
self.rootNode = rootNode
}
let parent: NodeOutput?
let rootNode: NodeOutput?
var isEnabled: Bool = true
private(set) var outputPath: CGPath? = nil
private(set) var transform: CATransform3D = CATransform3DIdentity
func setTransform(_ xform: CATransform3D, forFrame: CGFloat) {
transform = xform
outputPath = nil
}
func hasOutputUpdates(_ forFrame: CGFloat) -> Bool {
guard isEnabled else {
let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
outputPath = parent?.outputPath
return upstreamUpdates
}
let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
if upstreamUpdates {
outputPath = nil
}
let rootUpdates = rootNode?.hasOutputUpdates(forFrame) ?? false
if rootUpdates {
outputPath = nil
}
var localUpdates: Bool = false
if outputPath == nil {
localUpdates = true
let newPath = CGMutablePath()
if let parentNode = parent, let parentPath = parentNode.outputPath {
/// First add parent path.
newPath.addPath(parentPath)
}
var xform = CATransform3DGetAffineTransform(transform)
if let rootNode = rootNode,
let rootPath = rootNode.outputPath,
let xformedPath = rootPath.copy(using: &xform) {
/// Now add root path. Note root path is transformed.
newPath.addPath(xformedPath)
}
outputPath = newPath
}
return upstreamUpdates || localUpdates
}
}

View File

@ -0,0 +1,43 @@
//
// PassThroughOutputNode.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import CoreGraphics
class PassThroughOutputNode: NodeOutput {
init(parent: NodeOutput?) {
self.parent = parent
}
let parent: NodeOutput?
var hasUpdate: Bool = false
var isEnabled: Bool = true
func hasOutputUpdates(_ forFrame: CGFloat) -> Bool {
/// Changes to this node do not affect downstream nodes.
let parentUpdate = parent?.hasOutputUpdates(forFrame) ?? false
/// Changes to upstream nodes do, however, affect this nodes state.
hasUpdate = hasUpdate || parentUpdate
return parentUpdate
}
var outputPath: CGPath? {
if let parent = parent {
return parent.outputPath
}
return nil
}
func hasRenderUpdates(_ forFrame: CGFloat) -> Bool {
/// Return true if there are upstream updates or if this node has updates
let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
hasUpdate = hasUpdate || upstreamUpdates
return hasUpdate
}
}

View File

@ -0,0 +1,88 @@
//
// PathNodeOutput.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import CoreGraphics
/// A node that has an output of a BezierPath
class PathOutputNode: NodeOutput {
init(parent: NodeOutput?) {
self.parent = parent
}
let parent: NodeOutput?
fileprivate(set) var outputPath: CGPath? = nil
var lastUpdateFrame: CGFloat? = nil
var lastPathBuildFrame: CGFloat? = nil
var isEnabled: Bool = true
func hasOutputUpdates(_ forFrame: CGFloat) -> Bool {
guard isEnabled else {
let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
outputPath = parent?.outputPath
return upstreamUpdates
}
/// Ask if parent was updated
let upstreamUpdates = parent?.hasOutputUpdates(forFrame) ?? false
/// If parent was updated and the path hasn't been built for this frame, clear the path.
if upstreamUpdates && lastPathBuildFrame != forFrame {
outputPath = nil
}
if outputPath == nil {
/// If the path is clear, build the new path.
lastPathBuildFrame = forFrame
let newPath = CGMutablePath()
if let parentNode = parent, let parentPath = parentNode.outputPath {
newPath.addPath(parentPath)
}
for path in pathObjects {
for subPath in path.paths {
newPath.addPath(subPath.cgPath())
}
}
outputPath = newPath
}
/// Return true if there were upstream updates or if this node was updated.
return upstreamUpdates || (lastUpdateFrame == forFrame)
}
// MARK: Internal
fileprivate(set) var totalLength: CGFloat = 0
fileprivate(set) var pathObjects: [CompoundBezierPath] = []
@discardableResult func removePaths(updateFrame: CGFloat?) -> [CompoundBezierPath] {
lastUpdateFrame = updateFrame
let returnPaths = pathObjects
outputPath = nil
totalLength = 0
pathObjects = []
return returnPaths
}
func setPath(_ path: BezierPath, updateFrame: CGFloat) {
lastUpdateFrame = updateFrame
outputPath = nil
totalLength = path.length
pathObjects = [CompoundBezierPath(path: path)]
}
func appendPath(_ path: CompoundBezierPath, updateFrame: CGFloat) {
lastUpdateFrame = updateFrame
outputPath = nil
totalLength = totalLength + path.length
pathObjects.append(path)
}
}

View File

@ -0,0 +1,72 @@
//
// FillRenderer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import QuartzCore
import CoreGraphics
extension FillRule {
var cgFillRule: CGPathFillRule {
switch self {
case .evenOdd:
return .evenOdd
default:
return .winding
}
}
var caFillRule: CAShapeLayerFillRule {
switch self {
case .evenOdd:
return CAShapeLayerFillRule.evenOdd
default:
return CAShapeLayerFillRule.nonZero
}
}
}
/// A rendered for a Path Fill
final class FillRenderer: PassThroughOutputNode, Renderable {
let shouldRenderInContext: Bool = false
func updateShapeLayer(layer: CAShapeLayer) {
layer.fillColor = color
layer.opacity = Float(opacity)
layer.fillRule = fillRule.caFillRule
hasUpdate = false
}
var color: CGColor? {
didSet {
hasUpdate = true
}
}
var opacity: CGFloat = 0 {
didSet {
hasUpdate = true
}
}
var fillRule: FillRule = .none {
didSet {
hasUpdate = true
}
}
func render(_ inContext: CGContext) {
guard inContext.path != nil && inContext.path!.isEmpty == false else {
return
}
guard let color = color else { return }
hasUpdate = false
inContext.setAlpha(opacity * 0.01)
inContext.setFillColor(color)
inContext.fillPath(using: fillRule.cgFillRule)
}
}

View File

@ -0,0 +1,126 @@
//
// GradientFillRenderer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import QuartzCore
/// A rendered for a Path Fill
final class GradientFillRenderer: PassThroughOutputNode, Renderable {
var shouldRenderInContext: Bool = true
func updateShapeLayer(layer: CAShapeLayer) {
// Not applicable
}
func render(_ inContext: CGContext) {
guard inContext.path != nil && inContext.path!.isEmpty == false else {
return
}
hasUpdate = false
var alphaColors = [CGColor]()
var alphaLocations = [CGFloat]()
var gradientColors = [CGColor]()
var colorLocations = [CGFloat]()
let colorSpace = CGColorSpaceCreateDeviceRGB()
let maskColorSpace = CGColorSpaceCreateDeviceGray()
for i in 0..<numberOfColors {
let ix = i * 4
if colors.count > ix, let color = CGColor(colorSpace: colorSpace, components: [colors[ix + 1], colors[ix + 2], colors[ix + 3], 1]) {
gradientColors.append(color)
colorLocations.append(colors[ix])
}
}
var drawMask = false
for i in stride(from: (numberOfColors * 4), to: colors.endIndex, by: 2) {
let alpha = colors[i + 1]
if alpha < 1 {
drawMask = true
}
if let color = CGColor(colorSpace: maskColorSpace, components: [alpha, 1]) {
alphaLocations.append(colors[i])
alphaColors.append(color)
}
}
inContext.setAlpha(opacity)
inContext.clip()
/// First draw a mask is necessary.
if drawMask {
guard let maskGradient = CGGradient(colorsSpace: maskColorSpace,
colors: alphaColors as CFArray,
locations: alphaLocations),
let maskContext = CGContext(data: nil,
width: inContext.width,
height: inContext.height,
bitsPerComponent: 8,
bytesPerRow: inContext.width,
space: maskColorSpace,
bitmapInfo: 0) else { return }
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: CGFloat(maskContext.height))
maskContext.concatenate(flipVertical)
maskContext.concatenate(inContext.ctm)
if type == .linear {
maskContext.drawLinearGradient(maskGradient, start: start, end: end, options: [.drawsAfterEndLocation, .drawsBeforeStartLocation])
} else {
maskContext.drawRadialGradient(maskGradient, startCenter: start, startRadius: 0, endCenter: start, endRadius: start.distanceTo(end), options: [.drawsAfterEndLocation, .drawsBeforeStartLocation])
}
/// Clips the gradient
if let alphaMask = maskContext.makeImage() {
inContext.clip(to: inContext.boundingBoxOfClipPath, mask: alphaMask)
}
}
/// Now draw the gradient
guard let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors as CFArray, locations: colorLocations) else { return }
if type == .linear {
inContext.drawLinearGradient(gradient, start: start, end: end, options: [.drawsAfterEndLocation, .drawsBeforeStartLocation])
} else {
inContext.drawRadialGradient(gradient, startCenter: start, startRadius: 0, endCenter: start, endRadius: start.distanceTo(end), options: [.drawsAfterEndLocation, .drawsBeforeStartLocation])
}
}
var start: CGPoint = .zero {
didSet {
hasUpdate = true
}
}
var numberOfColors: Int = 0 {
didSet {
hasUpdate = true
}
}
var colors: [CGFloat] = [] {
didSet {
hasUpdate = true
}
}
var end: CGPoint = .zero {
didSet {
hasUpdate = true
}
}
var opacity: CGFloat = 0 {
didSet {
hasUpdate = true
}
}
var type: GradientType = .none {
didSet {
hasUpdate = true
}
}
}

View File

@ -0,0 +1,59 @@
//
// GradientStrokeRenderer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import QuartzCore
// MARK: - Renderer
final class GradientStrokeRenderer: PassThroughOutputNode, Renderable {
override func hasOutputUpdates(_ forFrame: CGFloat) -> Bool {
let updates = super.hasOutputUpdates(forFrame)
return updates || strokeRender.hasUpdate || gradientRender.hasUpdate
}
var shouldRenderInContext: Bool = true
func updateShapeLayer(layer: CAShapeLayer) {
/// Not Applicable
}
let strokeRender: StrokeRenderer
let gradientRender: GradientFillRenderer
override init(parent: NodeOutput?) {
self.strokeRender = StrokeRenderer(parent: nil)
self.gradientRender = GradientFillRenderer(parent: nil)
self.strokeRender.color = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1, 1, 1, 1])
super.init(parent: parent)
}
func render(_ inContext: CGContext) {
guard inContext.path != nil && inContext.path!.isEmpty == false else {
return
}
strokeRender.hasUpdate = false
hasUpdate = false
gradientRender.hasUpdate = false
strokeRender.setupForStroke(inContext)
inContext.replacePathWithStrokedPath()
/// Now draw the gradient.
gradientRender.render(inContext)
}
func renderBoundsFor(_ boundingBox: CGRect) -> CGRect {
return strokeRender.renderBoundsFor(boundingBox)
}
}

View File

@ -0,0 +1,162 @@
//
// StrokeRenderer.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/30/19.
//
import Foundation
import QuartzCore
extension LineJoin {
var cgLineJoin: CGLineJoin {
switch self {
case .bevel:
return .bevel
case .none:
return .miter
case .miter:
return .miter
case .round:
return .round
}
}
var caLineJoin: CAShapeLayerLineJoin {
switch self {
case .none:
return CAShapeLayerLineJoin.miter
case .miter:
return CAShapeLayerLineJoin.miter
case .round:
return CAShapeLayerLineJoin.round
case .bevel:
return CAShapeLayerLineJoin.bevel
}
}
}
extension LineCap {
var cgLineCap: CGLineCap {
switch self {
case .none:
return .butt
case .butt:
return .butt
case .round:
return .round
case .square:
return .square
}
}
var caLineCap: CAShapeLayerLineCap {
switch self {
case .none:
return CAShapeLayerLineCap.butt
case .butt:
return CAShapeLayerLineCap.butt
case .round:
return CAShapeLayerLineCap.round
case .square:
return CAShapeLayerLineCap.square
}
}
}
// MARK: - Renderer
/// A rendered that renders a stroke on a path.
final class StrokeRenderer: PassThroughOutputNode, Renderable {
var shouldRenderInContext: Bool = false
var color: CGColor? {
didSet {
hasUpdate = true
}
}
var opacity: CGFloat = 0 {
didSet {
hasUpdate = true
}
}
var width: CGFloat = 0 {
didSet {
hasUpdate = true
}
}
var miterLimit: CGFloat = 0 {
didSet {
hasUpdate = true
}
}
var lineCap: LineCap = .none {
didSet {
hasUpdate = true
}
}
var lineJoin: LineJoin = .none {
didSet {
hasUpdate = true
}
}
var dashPhase: CGFloat? {
didSet {
hasUpdate = true
}
}
var dashLengths: [CGFloat]? {
didSet {
hasUpdate = true
}
}
func renderBoundsFor(_ boundingBox: CGRect) -> CGRect {
return boundingBox.insetBy(dx: -width, dy: -width)
}
func setupForStroke(_ inContext: CGContext) {
inContext.setLineWidth(width)
inContext.setMiterLimit(miterLimit)
inContext.setLineCap(lineCap.cgLineCap)
inContext.setLineJoin(lineJoin.cgLineJoin)
if let dashPhase = dashPhase, let lengths = dashLengths {
inContext.setLineDash(phase: dashPhase, lengths: lengths)
} else {
inContext.setLineDash(phase: 0, lengths: [])
}
}
func render(_ inContext: CGContext) {
guard inContext.path != nil && inContext.path!.isEmpty == false else {
return
}
guard let color = color else { return }
hasUpdate = false
setupForStroke(inContext)
inContext.setAlpha(opacity)
inContext.setStrokeColor(color)
inContext.strokePath()
}
func updateShapeLayer(layer: CAShapeLayer) {
layer.strokeColor = color
layer.opacity = Float(opacity)
layer.lineWidth = width
layer.lineJoin = lineJoin.caLineJoin
layer.lineCap = lineCap.caLineCap
layer.lineDashPhase = dashPhase ?? 0
layer.fillColor = nil
if let dashPattern = dashLengths {
layer.lineDashPattern = dashPattern.map({ NSNumber(value: Double($0)) })
}
}
}

View File

@ -0,0 +1,109 @@
//
// EllipseNode.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/17/19.
//
import Foundation
import QuartzCore
final class EllipseNodeProperties: NodePropertyMap, KeypathSearchable {
var keypathName: String
init(ellipse: Ellipse) {
self.keypathName = ellipse.name
self.direction = ellipse.direction
self.position = NodeProperty(provider: KeyframeInterpolator(keyframes: ellipse.position.keyframes))
self.size = NodeProperty(provider: KeyframeInterpolator(keyframes: ellipse.size.keyframes))
self.keypathProperties = [
"Position" : position,
"Size" : size
]
self.properties = Array(keypathProperties.values)
}
let direction: PathDirection
let position: NodeProperty<Vector3D>
let size: NodeProperty<Vector3D>
let keypathProperties: [String : AnyNodeProperty]
let properties: [AnyNodeProperty]
}
final class EllipseNode: AnimatorNode, PathNode {
let pathOutput: PathOutputNode
let properties: EllipseNodeProperties
init(parentNode: AnimatorNode?, ellipse: Ellipse) {
self.pathOutput = PathOutputNode(parent: parentNode?.outputNode)
self.properties = EllipseNodeProperties(ellipse: ellipse)
self.parentNode = parentNode
}
// MARK: Animator Node
var propertyMap: NodePropertyMap & KeypathSearchable {
return properties
}
let parentNode: AnimatorNode?
var hasLocalUpdates: Bool = false
var hasUpstreamUpdates: Bool = false
var lastUpdateFrame: CGFloat? = nil
var isEnabled: Bool = true {
didSet{
self.pathOutput.isEnabled = self.isEnabled
}
}
func rebuildOutputs(frame: CGFloat) {
let ellipseSize = properties.size.value.sizeValue
let center = properties.position.value.pointValue
// Unfortunately we HAVE to manually build out the ellipse.
// Every Apple method constructs an ellipse from the 3 o-clock position
// After effects constructs from the Noon position.
// After effects does clockwise, but also has a flag for reversed.
var half = ellipseSize * 0.5
if properties.direction == .counterClockwise {
half.width = half.width * -1
}
let q1 = CGPoint(x: center.x, y: center.y - half.height)
let q2 = CGPoint(x: center.x + half.width, y: center.y)
let q3 = CGPoint(x: center.x, y: center.y + half.height)
let q4 = CGPoint(x: center.x - half.width, y: center.y)
let cp = half * EllipseNode.ControlPointConstant
var path = BezierPath(startPoint: CurveVertex(point: q1,
inTangentRelative: CGPoint(x: -cp.width, y: 0),
outTangentRelative: CGPoint(x: cp.width, y: 0)))
path.addVertex(CurveVertex(point: q2,
inTangentRelative: CGPoint(x: 0, y: -cp.height),
outTangentRelative: CGPoint(x: 0, y: cp.height)))
path.addVertex(CurveVertex(point: q3,
inTangentRelative: CGPoint(x: cp.width, y: 0),
outTangentRelative: CGPoint(x: -cp.width, y: 0)))
path.addVertex(CurveVertex(point: q4,
inTangentRelative: CGPoint(x: 0, y: cp.height),
outTangentRelative: CGPoint(x: 0, y: -cp.height)))
path.addVertex(CurveVertex(point: q1,
inTangentRelative: CGPoint(x: -cp.width, y: 0),
outTangentRelative: CGPoint(x: cp.width, y: 0)))
path.close()
pathOutput.setPath(path, updateFrame: frame)
}
static let ControlPointConstant: CGFloat = 0.55228
}

View File

@ -0,0 +1,132 @@
//
// PolygonNode.swift
// lottie-swift
//
// Created by Brandon Withrow on 1/21/19.
//
import Foundation
import QuartzCore
final class PolygonNodeProperties: NodePropertyMap, KeypathSearchable {
var keypathName: String
var childKeypaths: [KeypathSearchable] = []
init(star: Star) {
self.keypathName = star.name
self.direction = star.direction
self.position = NodeProperty(provider: KeyframeInterpolator(keyframes: star.position.keyframes))
self.outerRadius = NodeProperty(provider: KeyframeInterpolator(keyframes: star.outerRadius.keyframes))
self.outerRoundedness = NodeProperty(provider: KeyframeInterpolator(keyframes: star.outerRoundness.keyframes))
self.rotation = NodeProperty(provider: KeyframeInterpolator(keyframes: star.rotation.keyframes))
self.points = NodeProperty(provider: KeyframeInterpolator(keyframes: star.points.keyframes))
self.keypathProperties = [
"Position" : position,
"Outer Radius" : outerRadius,
"Outer Roundedness" : outerRoundedness,
"Rotation" : rotation,
"Points" : points
]
self.properties = Array(keypathProperties.values)
}
let keypathProperties: [String : AnyNodeProperty]
let properties: [AnyNodeProperty]
let direction: PathDirection
let position: NodeProperty<Vector3D>
let outerRadius: NodeProperty<Vector1D>
let outerRoundedness: NodeProperty<Vector1D>
let rotation: NodeProperty<Vector1D>
let points: NodeProperty<Vector1D>
}
final class PolygonNode: AnimatorNode, PathNode {
let properties: PolygonNodeProperties
let pathOutput: PathOutputNode
init(parentNode: AnimatorNode?, star: Star) {
self.pathOutput = PathOutputNode(parent: parentNode?.outputNode)
self.properties = PolygonNodeProperties(star: star)
self.parentNode = parentNode
}
// MARK: Animator Node
var propertyMap: NodePropertyMap & KeypathSearchable {
return properties
}
let parentNode: AnimatorNode?
var hasLocalUpdates: Bool = false
var hasUpstreamUpdates: Bool = false
var lastUpdateFrame: CGFloat? = nil
var isEnabled: Bool = true {
didSet{
self.pathOutput.isEnabled = self.isEnabled
}
}
/// Magic number needed for constructing path.
static let PolygonConstant: CGFloat = 0.25
func rebuildOutputs(frame: CGFloat) {
let outerRadius = properties.outerRadius.value.cgFloatValue
let outerRoundedness = properties.outerRoundedness.value.cgFloatValue * 0.01
let numberOfPoints = properties.points.value.cgFloatValue
let rotation = properties.rotation.value.cgFloatValue
let position = properties.position.value.pointValue
var currentAngle = (rotation - 90).toRadians()
let anglePerPoint = ((2 * CGFloat.pi) / numberOfPoints)
var point = CGPoint(x: (outerRadius * cos(currentAngle)),
y: (outerRadius * sin(currentAngle)))
var vertices = [CurveVertex(point: point + position, inTangentRelative: .zero, outTangentRelative: .zero)]
var previousPoint = point
currentAngle += anglePerPoint;
for _ in 0..<Int(ceil(numberOfPoints)) {
previousPoint = point
point = CGPoint(x: (outerRadius * cos(currentAngle)),
y: (outerRadius * sin(currentAngle)))
if outerRoundedness != 0 {
let cp1Theta = (atan2(previousPoint.y, previousPoint.x) - CGFloat.pi / 2)
let cp1Dx = cos(cp1Theta);
let cp1Dy = sin(cp1Theta);
let cp2Theta = (atan2(point.y, point.x) - CGFloat.pi / 2)
let cp2Dx = cos(cp2Theta)
let cp2Dy = sin(cp2Theta)
let cp1 = CGPoint(x: outerRadius * outerRoundedness * PolygonNode.PolygonConstant * cp1Dx,
y: outerRadius * outerRoundedness * PolygonNode.PolygonConstant * cp1Dy)
let cp2 = CGPoint(x: outerRadius * outerRoundedness * PolygonNode.PolygonConstant * cp2Dx,
y: outerRadius * outerRoundedness * PolygonNode.PolygonConstant * cp2Dy)
let previousVertex = vertices[vertices.endIndex-1]
vertices[vertices.endIndex-1] = CurveVertex(previousVertex.inTangent, previousVertex.point, previousVertex.point - cp1 + position)
vertices.append(CurveVertex(point: point + position, inTangentRelative: cp2, outTangentRelative: .zero))
} else {
vertices.append(CurveVertex(point: point + position, inTangentRelative: .zero, outTangentRelative: .zero))
}
currentAngle += anglePerPoint;
}
let reverse = properties.direction == .counterClockwise
if reverse {
vertices = vertices.reversed()
}
var path = BezierPath()
for vertex in vertices {
path.addVertex(reverse ? vertex.reversed() : vertex)
}
path.close()
pathOutput.setPath(path, updateFrame: frame)
}
}

Some files were not shown because too many files have changed in this diff Show More