Add settings page
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
@@ -58,7 +58,7 @@
|
|||||||
"react-native/no-unused-styles": "error",
|
"react-native/no-unused-styles": "error",
|
||||||
"react-native/no-inline-styles": "error",
|
"react-native/no-inline-styles": "error",
|
||||||
"react-native/no-color-literals": "error",
|
"react-native/no-color-literals": "error",
|
||||||
"react-native/no-raw-text": "error",
|
"react-native/no-raw-text": "off",
|
||||||
"no-shadow": "off",
|
"no-shadow": "off",
|
||||||
"@typescript-eslint/no-shadow": ["error"],
|
"@typescript-eslint/no-shadow": ["error"],
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
|
@@ -118,6 +118,8 @@ dependencies {
|
|||||||
} else {
|
} else {
|
||||||
implementation jscFlavor
|
implementation jscFlavor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implementation project(':react-native-fs')
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
|
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
|
||||||
|
@@ -2,3 +2,6 @@ rootProject.name = 'TerminallyOnline'
|
|||||||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
|
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
|
||||||
include ':app'
|
include ':app'
|
||||||
includeBuild('../node_modules/@react-native/gradle-plugin')
|
includeBuild('../node_modules/@react-native/gradle-plugin')
|
||||||
|
|
||||||
|
include ':react-native-fs'
|
||||||
|
project(':react-native-fs').projectDir = new File(settingsDir, '../node_modules/react-native-fs/android')
|
||||||
|
115
package-lock.json
generated
115
package-lock.json
generated
@@ -9,6 +9,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@react-native-async-storage/async-storage": "^1.19.0",
|
||||||
"@react-navigation/bottom-tabs": "^6.5.8",
|
"@react-navigation/bottom-tabs": "^6.5.8",
|
||||||
"@react-navigation/drawer": "^6.6.3",
|
"@react-navigation/drawer": "^6.6.3",
|
||||||
"@react-navigation/native": "^6.1.7",
|
"@react-navigation/native": "^6.1.7",
|
||||||
@@ -16,10 +17,12 @@
|
|||||||
"@realm/react": "^0.5.1",
|
"@realm/react": "^0.5.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-native": "0.72.1",
|
"react-native": "0.72.1",
|
||||||
|
"react-native-fs": "^2.20.0",
|
||||||
"react-native-gesture-handler": "^2.12.0",
|
"react-native-gesture-handler": "^2.12.0",
|
||||||
"react-native-paper": "^5.9.1",
|
"react-native-paper": "^5.9.1",
|
||||||
"react-native-reanimated": "2.2.4",
|
"react-native-reanimated": "2.2.4",
|
||||||
"react-native-safe-area-context": "^4.6.4",
|
"react-native-safe-area-context": "^4.6.4",
|
||||||
|
"react-native-scoped-storage": "^1.9.3",
|
||||||
"react-native-screens": "^3.22.1",
|
"react-native-screens": "^3.22.1",
|
||||||
"react-native-vector-icons": "^9.2.0",
|
"react-native-vector-icons": "^9.2.0",
|
||||||
"realm": "^11.10.1"
|
"realm": "^11.10.1"
|
||||||
@@ -3013,6 +3016,17 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-native-async-storage/async-storage": {
|
||||||
|
"version": "1.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.19.0.tgz",
|
||||||
|
"integrity": "sha512-xOFkz/FaQctD6yNJDur+WnHdSTigOs3pTz6HmfC8X8PYwcnnN3R9UxuWiwsfK8vvT2WioAxUkQt3lB7GySNA2w==",
|
||||||
|
"dependencies": {
|
||||||
|
"merge-options": "^3.0.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react-native": "^0.0.0-0 || 0.60 - 0.72 || 1000.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@react-native-community/cli": {
|
"node_modules/@react-native-community/cli": {
|
||||||
"version": "11.3.3",
|
"version": "11.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.3.tgz",
|
||||||
@@ -5306,6 +5320,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/base-64": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
|
||||||
|
},
|
||||||
"node_modules/base64-js": {
|
"node_modules/base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
@@ -8377,6 +8396,14 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-plain-obj": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-plain-object": {
|
"node_modules/is-plain-object": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
||||||
@@ -10719,6 +10746,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||||
},
|
},
|
||||||
|
"node_modules/merge-options": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-plain-obj": "^2.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/merge-stream": {
|
"node_modules/merge-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||||
@@ -12721,6 +12759,24 @@
|
|||||||
"react": "18.2.0"
|
"react": "18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-fs": {
|
||||||
|
"version": "2.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz",
|
||||||
|
"integrity": "sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"base-64": "^0.1.0",
|
||||||
|
"utf8": "^3.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react-native": "*",
|
||||||
|
"react-native-windows": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-native-windows": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-gesture-handler": {
|
"node_modules/react-native-gesture-handler": {
|
||||||
"version": "2.12.0",
|
"version": "2.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.12.0.tgz",
|
||||||
@@ -12780,6 +12836,14 @@
|
|||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-scoped-storage": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-scoped-storage/-/react-native-scoped-storage-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-hGqj+2I6pIziIh1CmWXXlgm59wCQLIikETqbMCaFQRHC3yQGI4HdYN6QvM3rteUuR69PNjso+Qd3TJfQnFhlMA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-screens": {
|
"node_modules/react-native-screens": {
|
||||||
"version": "3.22.1",
|
"version": "3.22.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.22.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.22.1.tgz",
|
||||||
@@ -14667,6 +14731,11 @@
|
|||||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/utf8": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ=="
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@@ -17051,6 +17120,14 @@
|
|||||||
"fastq": "^1.6.0"
|
"fastq": "^1.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@react-native-async-storage/async-storage": {
|
||||||
|
"version": "1.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.19.0.tgz",
|
||||||
|
"integrity": "sha512-xOFkz/FaQctD6yNJDur+WnHdSTigOs3pTz6HmfC8X8PYwcnnN3R9UxuWiwsfK8vvT2WioAxUkQt3lB7GySNA2w==",
|
||||||
|
"requires": {
|
||||||
|
"merge-options": "^3.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@react-native-community/cli": {
|
"@react-native-community/cli": {
|
||||||
"version": "11.3.3",
|
"version": "11.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.3.tgz",
|
||||||
@@ -18804,6 +18881,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"base-64": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
|
||||||
|
},
|
||||||
"base64-js": {
|
"base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
@@ -21034,6 +21116,11 @@
|
|||||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"is-plain-obj": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="
|
||||||
|
},
|
||||||
"is-plain-object": {
|
"is-plain-object": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
||||||
@@ -22790,6 +22877,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
|
||||||
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
|
||||||
},
|
},
|
||||||
|
"merge-options": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==",
|
||||||
|
"requires": {
|
||||||
|
"is-plain-obj": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"merge-stream": {
|
"merge-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||||
@@ -24349,6 +24444,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-native-fs": {
|
||||||
|
"version": "2.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz",
|
||||||
|
"integrity": "sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==",
|
||||||
|
"requires": {
|
||||||
|
"base-64": "^0.1.0",
|
||||||
|
"utf8": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-native-gesture-handler": {
|
"react-native-gesture-handler": {
|
||||||
"version": "2.12.0",
|
"version": "2.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.12.0.tgz",
|
||||||
@@ -24389,6 +24493,12 @@
|
|||||||
"integrity": "sha512-UWYsokTLZmj8g0cluzoUeGUjQrCTW4slKr2xKmuwQCurAuvSJq/QvfhCrqyea++XrXo46+1Q3wSoP50YXG24jA==",
|
"integrity": "sha512-UWYsokTLZmj8g0cluzoUeGUjQrCTW4slKr2xKmuwQCurAuvSJq/QvfhCrqyea++XrXo46+1Q3wSoP50YXG24jA==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
|
"react-native-scoped-storage": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-scoped-storage/-/react-native-scoped-storage-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-hGqj+2I6pIziIh1CmWXXlgm59wCQLIikETqbMCaFQRHC3yQGI4HdYN6QvM3rteUuR69PNjso+Qd3TJfQnFhlMA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"react-native-screens": {
|
"react-native-screens": {
|
||||||
"version": "3.22.1",
|
"version": "3.22.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.22.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.22.1.tgz",
|
||||||
@@ -25742,6 +25852,11 @@
|
|||||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
|
"utf8": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ=="
|
||||||
|
},
|
||||||
"util-deprecate": {
|
"util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
"compile": "export $(cat .env | xargs) && cd android && ./gradlew assembleRelease && cd .."
|
"compile": "export $(cat .env | xargs) && cd android && ./gradlew assembleRelease && cd .."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@react-native-async-storage/async-storage": "^1.19.0",
|
||||||
"@react-navigation/bottom-tabs": "^6.5.8",
|
"@react-navigation/bottom-tabs": "^6.5.8",
|
||||||
"@react-navigation/drawer": "^6.6.3",
|
"@react-navigation/drawer": "^6.6.3",
|
||||||
"@react-navigation/native": "^6.1.7",
|
"@react-navigation/native": "^6.1.7",
|
||||||
@@ -20,10 +21,12 @@
|
|||||||
"@realm/react": "^0.5.1",
|
"@realm/react": "^0.5.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-native": "0.72.1",
|
"react-native": "0.72.1",
|
||||||
|
"react-native-fs": "^2.20.0",
|
||||||
"react-native-gesture-handler": "^2.12.0",
|
"react-native-gesture-handler": "^2.12.0",
|
||||||
"react-native-paper": "^5.9.1",
|
"react-native-paper": "^5.9.1",
|
||||||
"react-native-reanimated": "2.2.4",
|
"react-native-reanimated": "2.2.4",
|
||||||
"react-native-safe-area-context": "^4.6.4",
|
"react-native-safe-area-context": "^4.6.4",
|
||||||
|
"react-native-scoped-storage": "^1.9.3",
|
||||||
"react-native-screens": "^3.22.1",
|
"react-native-screens": "^3.22.1",
|
||||||
"react-native-vector-icons": "^9.2.0",
|
"react-native-vector-icons": "^9.2.0",
|
||||||
"realm": "^11.10.1"
|
"realm": "^11.10.1"
|
||||||
|
38
src/app.tsx
38
src/app.tsx
@@ -1,47 +1,31 @@
|
|||||||
import React from 'react';
|
import React, { JSX } from 'react';
|
||||||
import { Appearance, StatusBar } from 'react-native';
|
import { Appearance, StatusBar } from 'react-native';
|
||||||
import { NavigationContainer } from '@react-navigation/native';
|
|
||||||
import { createMaterialBottomTabNavigator } from 'react-native-paper/react-navigation';
|
|
||||||
import { PaperProvider } from 'react-native-paper';
|
import { PaperProvider } from 'react-native-paper';
|
||||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
|
import { RealmProvider } from '@realm/react';
|
||||||
import Home from './screens/home';
|
|
||||||
import { lightTheme, darkTheme } from './theme';
|
import { lightTheme, darkTheme } from './theme';
|
||||||
import { Meme, Tag } from './database';
|
import { Meme, Tag } from './database';
|
||||||
import { createRealmContext } from '@realm/react';
|
import NavigationContainer from './navigation';
|
||||||
|
import { SettingsProvider } from './contexts/settings';
|
||||||
const TabNavigator = createMaterialBottomTabNavigator();
|
|
||||||
|
|
||||||
const { RealmProvider } = createRealmContext({
|
|
||||||
schema: [Meme, Tag],
|
|
||||||
});
|
|
||||||
|
|
||||||
function App(): JSX.Element {
|
function App(): JSX.Element {
|
||||||
const colorScheme = Appearance.getColorScheme();
|
const colorScheme = Appearance.getColorScheme();
|
||||||
const theme = colorScheme === 'dark' ? lightTheme : darkTheme;
|
const theme = colorScheme === 'dark' ? lightTheme : darkTheme;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RealmProvider>
|
<RealmProvider schema={[Meme, Tag]}>
|
||||||
<PaperProvider theme={theme}>
|
<PaperProvider theme={theme}>
|
||||||
|
<SettingsProvider>
|
||||||
<SafeAreaProvider>
|
<SafeAreaProvider>
|
||||||
<StatusBar
|
<StatusBar
|
||||||
barStyle={colorScheme === 'dark' ? 'dark-content' : 'light-content'}
|
barStyle={
|
||||||
|
colorScheme === 'dark' ? 'dark-content' : 'light-content'
|
||||||
|
}
|
||||||
backgroundColor={theme.colors.background}
|
backgroundColor={theme.colors.background}
|
||||||
/>
|
/>
|
||||||
<NavigationContainer>
|
<NavigationContainer />
|
||||||
<TabNavigator.Navigator>
|
|
||||||
<TabNavigator.Screen
|
|
||||||
name="Home"
|
|
||||||
component={Home}
|
|
||||||
options={{
|
|
||||||
tabBarIcon: ({ color }) => (
|
|
||||||
<FontAwesome5 name="home" color={color} size={20} />
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</TabNavigator.Navigator>
|
|
||||||
</NavigationContainer>
|
|
||||||
</SafeAreaProvider>
|
</SafeAreaProvider>
|
||||||
|
</SettingsProvider>
|
||||||
</PaperProvider>
|
</PaperProvider>
|
||||||
</RealmProvider>
|
</RealmProvider>
|
||||||
);
|
);
|
||||||
|
2
src/components/index.ts
Normal file
2
src/components/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { default as LoadingView } from './loadingView';
|
||||||
|
export { default as PaddedView } from './paddedView';
|
23
src/components/loadingView.tsx
Normal file
23
src/components/loadingView.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { ActivityIndicator, StyleSheet, View } from 'react-native';
|
||||||
|
import { useTheme } from 'react-native-paper';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const LoadingView = () => {
|
||||||
|
const { colors } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, { backgroundColor: colors.background }]}>
|
||||||
|
<ActivityIndicator size="large" color={colors.primary} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LoadingView;
|
31
src/components/paddedView.tsx
Normal file
31
src/components/paddedView.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
padding: '5%',
|
||||||
|
},
|
||||||
|
centered: {
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const PaddedView = ({
|
||||||
|
children,
|
||||||
|
style,
|
||||||
|
centered,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
style?: StyleProp<ViewStyle>;
|
||||||
|
centered?: boolean;
|
||||||
|
}): React.JSX.Element => {
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, centered && styles.centered, style]}>
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PaddedView;
|
1
src/contexts/index.ts
Normal file
1
src/contexts/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { useSettings, SettingsProvider } from './settings';
|
81
src/contexts/settings.tsx
Normal file
81
src/contexts/settings.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||||
|
import { Settings } from '../types';
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
import { DocumentDirectoryPath } from 'react-native-fs';
|
||||||
|
import { LoadingView } from '../components';
|
||||||
|
|
||||||
|
interface SettingsContextType {
|
||||||
|
settings: Settings;
|
||||||
|
setSettings: (newSettings: Partial<Settings>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SettingsContext = createContext<SettingsContextType | undefined>(
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
|
||||||
|
const SettingsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const [settings, setSettings] = useState<Settings>({
|
||||||
|
useInternalStorage: true,
|
||||||
|
storageUri: '',
|
||||||
|
addNoMedia: false,
|
||||||
|
});
|
||||||
|
const [hasLoaded, setHasLoaded] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const loadSettings = async () => {
|
||||||
|
const useInternalStorageValue = await AsyncStorage.getItem(
|
||||||
|
'useInternalStorage',
|
||||||
|
);
|
||||||
|
const storageUriValue = await AsyncStorage.getItem('storageUri');
|
||||||
|
const addNoMediaValue = await AsyncStorage.getItem('addNoMedia');
|
||||||
|
|
||||||
|
setSettings({
|
||||||
|
useInternalStorage: useInternalStorageValue
|
||||||
|
? (JSON.parse(useInternalStorageValue) as boolean)
|
||||||
|
: true,
|
||||||
|
storageUri: storageUriValue ?? DocumentDirectoryPath,
|
||||||
|
addNoMedia: addNoMediaValue
|
||||||
|
? (JSON.parse(addNoMediaValue) as boolean)
|
||||||
|
: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
setHasLoaded(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
void loadSettings();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const updateSettings = (newSettings: Partial<Settings>) => {
|
||||||
|
const updatedSettings = { ...settings, ...newSettings };
|
||||||
|
|
||||||
|
void AsyncStorage.setItem(
|
||||||
|
'useInternalStorage',
|
||||||
|
JSON.stringify(updatedSettings.useInternalStorage),
|
||||||
|
);
|
||||||
|
void AsyncStorage.setItem('storageUri', updatedSettings.storageUri);
|
||||||
|
void AsyncStorage.setItem(
|
||||||
|
'addNoMedia',
|
||||||
|
JSON.stringify(updatedSettings.addNoMedia),
|
||||||
|
);
|
||||||
|
|
||||||
|
setSettings(updatedSettings);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsContext.Provider value={{ settings, setSettings: updateSettings }}>
|
||||||
|
{hasLoaded ? children : <LoadingView />}
|
||||||
|
</SettingsContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const useSettings = (): SettingsContextType => {
|
||||||
|
const context = useContext(SettingsContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useSettings must be used within a SettingsProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { SettingsProvider, useSettings };
|
86
src/navigation.tsx
Normal file
86
src/navigation.tsx
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
CommonActions,
|
||||||
|
NavigationContainer as NavigationContainerBase,
|
||||||
|
} from '@react-navigation/native';
|
||||||
|
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
|
||||||
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
|
import { BottomNavigation, useTheme } from 'react-native-paper';
|
||||||
|
import { Home, Settings } from './screens';
|
||||||
|
|
||||||
|
function NavigationContainer() {
|
||||||
|
const TabNavigator = createBottomTabNavigator();
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavigationContainerBase
|
||||||
|
theme={{
|
||||||
|
dark: theme.dark,
|
||||||
|
colors: {
|
||||||
|
primary: theme.colors.primary,
|
||||||
|
background: theme.colors.background,
|
||||||
|
card: theme.colors.surface,
|
||||||
|
text: theme.colors.onSurface,
|
||||||
|
border: theme.colors.outline,
|
||||||
|
notification: theme.colors.error,
|
||||||
|
},
|
||||||
|
}}>
|
||||||
|
<TabNavigator.Navigator
|
||||||
|
screenOptions={{
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
tabBar={({ navigation, state, descriptors, insets }) => (
|
||||||
|
<BottomNavigation.Bar
|
||||||
|
navigationState={state}
|
||||||
|
safeAreaInsets={insets}
|
||||||
|
onTabPress={({ route, preventDefault }) => {
|
||||||
|
const event = navigation.emit({
|
||||||
|
type: 'tabPress',
|
||||||
|
target: route.key,
|
||||||
|
canPreventDefault: true,
|
||||||
|
});
|
||||||
|
if (event.defaultPrevented) {
|
||||||
|
preventDefault();
|
||||||
|
} else {
|
||||||
|
navigation.dispatch({
|
||||||
|
...CommonActions.navigate(route.name, route.params),
|
||||||
|
target: state.key,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
renderIcon={({ route, focused, color }) => {
|
||||||
|
const { options } = descriptors[route.key];
|
||||||
|
if (options.tabBarIcon) {
|
||||||
|
return options.tabBarIcon({ focused, color, size: 24 });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
getLabelText={({ route }) => {
|
||||||
|
const { options } = descriptors[route.key];
|
||||||
|
return options.title ?? route.name;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}>
|
||||||
|
<TabNavigator.Screen
|
||||||
|
name="Home"
|
||||||
|
component={Home}
|
||||||
|
options={{
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<FontAwesome5 name="home" color={color} size={20} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TabNavigator.Screen
|
||||||
|
name="Settings"
|
||||||
|
component={Settings}
|
||||||
|
options={{
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<FontAwesome5 name="cog" color={color} size={20} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</TabNavigator.Navigator>
|
||||||
|
</NavigationContainerBase>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NavigationContainer;
|
@@ -1,21 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, StyleSheet } from 'react-native';
|
|
||||||
|
|
||||||
import { Text } from 'react-native-paper';
|
import { Text } from 'react-native-paper';
|
||||||
|
import { PaddedView } from '../components';
|
||||||
const styles = StyleSheet.create({
|
import { useSettings } from '../contexts';
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function Home(): JSX.Element {
|
function Home(): JSX.Element {
|
||||||
|
const { settings } = useSettings();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<PaddedView centered>
|
||||||
<Text>Home</Text>
|
<Text>Home</Text>
|
||||||
</View>
|
<Text>Settings: {JSON.stringify(settings)}</Text>
|
||||||
|
</PaddedView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
src/screens/index.ts
Normal file
2
src/screens/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { default as Home } from './home';
|
||||||
|
export { default as Settings } from './settings';
|
159
src/screens/settings.tsx
Normal file
159
src/screens/settings.tsx
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { View } from 'react-native';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Switch,
|
||||||
|
SegmentedButtons,
|
||||||
|
Text,
|
||||||
|
List,
|
||||||
|
Snackbar,
|
||||||
|
} from 'react-native-paper';
|
||||||
|
import { useRealm } from '@realm/react';
|
||||||
|
import { openDocumentTree } from 'react-native-scoped-storage';
|
||||||
|
import { DocumentDirectoryPath } from 'react-native-fs';
|
||||||
|
import { PaddedView } from '../components';
|
||||||
|
import styles from '../styles';
|
||||||
|
import { Meme } from '../database';
|
||||||
|
import { useSettings } from '../contexts';
|
||||||
|
|
||||||
|
const SettingsScreen = () => {
|
||||||
|
const [optimizingDatabase, setOptimizingDatabase] = useState(false);
|
||||||
|
|
||||||
|
const [snackbarVisible, setSnackbarVisible] = useState(false);
|
||||||
|
const [snackbarMessage, setSnackbarMessage] = useState('');
|
||||||
|
|
||||||
|
const { settings, setSettings } = useSettings();
|
||||||
|
|
||||||
|
const setUseInternalStorage = (use: boolean) => {
|
||||||
|
if (settings.useInternalStorage === use) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use) {
|
||||||
|
setSettings({
|
||||||
|
useInternalStorage: use,
|
||||||
|
storageUri: DocumentDirectoryPath,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
openDocumentTree(true)
|
||||||
|
.then(uri => {
|
||||||
|
setSettings({
|
||||||
|
useInternalStorage: use,
|
||||||
|
storageUri: uri.uri,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setSnackbarMessage('Failed to select storage path!');
|
||||||
|
setSnackbarVisible(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setStorageUri = (uri: string) => {
|
||||||
|
if (settings.storageUri === uri) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSettings({ storageUri: uri });
|
||||||
|
};
|
||||||
|
|
||||||
|
const setAddNoMedia = (add: boolean) => {
|
||||||
|
if (settings.addNoMedia === add) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSettings({ addNoMedia: add });
|
||||||
|
};
|
||||||
|
|
||||||
|
const realm = useRealm();
|
||||||
|
|
||||||
|
const optimizeDatabase = () => {
|
||||||
|
setOptimizingDatabase(true);
|
||||||
|
|
||||||
|
const memes = realm.objects<Meme>('Meme');
|
||||||
|
realm.write(() => {
|
||||||
|
for (let index = memes.length - 1; index >= 0; index--) {
|
||||||
|
// TODO: stat the uri to see if it exists and remove entry if it doesn't
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const success = realm.compact();
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
setSnackbarMessage('Database optimized!');
|
||||||
|
setSnackbarVisible(true);
|
||||||
|
} else {
|
||||||
|
setSnackbarMessage('Database optimization failed!');
|
||||||
|
setSnackbarVisible(true);
|
||||||
|
}
|
||||||
|
setOptimizingDatabase(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PaddedView>
|
||||||
|
<View>
|
||||||
|
<List.Section>
|
||||||
|
<List.Subheader>Database</List.Subheader>
|
||||||
|
<Button
|
||||||
|
mode="elevated"
|
||||||
|
style={styles.marginBottom}
|
||||||
|
loading={optimizingDatabase}
|
||||||
|
onPress={optimizeDatabase}>
|
||||||
|
Optimize Database Now
|
||||||
|
</Button>
|
||||||
|
</List.Section>
|
||||||
|
<List.Section>
|
||||||
|
<List.Subheader>Media Storage</List.Subheader>
|
||||||
|
<SegmentedButtons
|
||||||
|
style={styles.marginBottom}
|
||||||
|
buttons={[
|
||||||
|
{ label: 'Internal', value: 'interneal' },
|
||||||
|
{ label: 'External', value: 'external' },
|
||||||
|
]}
|
||||||
|
value={settings.useInternalStorage ? 'interneal' : 'external'}
|
||||||
|
onValueChange={value =>
|
||||||
|
setUseInternalStorage(value === 'interneal')
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
mode="elevated"
|
||||||
|
style={styles.marginBottom}
|
||||||
|
disabled={settings.useInternalStorage}
|
||||||
|
onPress={() => {
|
||||||
|
openDocumentTree(true)
|
||||||
|
.then(uri => {
|
||||||
|
setStorageUri(uri.uri);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setSnackbarMessage('Failed to select storage path!');
|
||||||
|
setSnackbarVisible(true);
|
||||||
|
});
|
||||||
|
}}>
|
||||||
|
Change External Storage Path
|
||||||
|
</Button>
|
||||||
|
<View style={styles.spaceBetweenHorizontal}>
|
||||||
|
<Text>Hide media from Gallery</Text>
|
||||||
|
<Switch
|
||||||
|
value={settings.addNoMedia}
|
||||||
|
onValueChange={setAddNoMedia}
|
||||||
|
disabled={settings.useInternalStorage}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</List.Section>
|
||||||
|
</View>
|
||||||
|
</PaddedView>
|
||||||
|
<Snackbar
|
||||||
|
visible={snackbarVisible}
|
||||||
|
onDismiss={() => setSnackbarVisible(false)}
|
||||||
|
action={{
|
||||||
|
label: 'Dismiss',
|
||||||
|
onPress: () => setSnackbarVisible(false),
|
||||||
|
}}>
|
||||||
|
{snackbarMessage}
|
||||||
|
</Snackbar>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SettingsScreen;
|
14
src/styles.tsx
Normal file
14
src/styles.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
marginBottom: {
|
||||||
|
marginBottom: 15,
|
||||||
|
},
|
||||||
|
spaceBetweenHorizontal: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default styles;
|
1
src/types/index.ts
Normal file
1
src/types/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export type { default as Settings } from './settings';
|
7
src/types/settings.ts
Normal file
7
src/types/settings.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
interface Settings {
|
||||||
|
useInternalStorage: boolean;
|
||||||
|
storageUri: string;
|
||||||
|
addNoMedia: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Settings;
|
Reference in New Issue
Block a user