@ -0,0 +1,4 @@ |
|||
squarenotsquare/ios/squarenotsquare.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist |
|||
squarenotsquare/ios/squarenotsquare.xcworkspace/contents.xcworkspacedata |
|||
squarenotsquare/ios/squarenotsquare.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist |
|||
.DS_Store |
@ -1,2 +1,32 @@ |
|||
# squarenotsquare |
|||
|
|||
## Dependencies |
|||
- Node version 18 |
|||
|
|||
## Running the app |
|||
- Clone the repo |
|||
- Navigate to the directory in a cli with node accessible |
|||
- Run the command **npm install** |
|||
- Wait for the installation to complete |
|||
- Start an Android or iOS simulator (or connect a device with USB debugging configured) |
|||
- In the cli, pass the command **npm run android** or **npm run ios** |
|||
- Wait for the build to complete and install on the device |
|||
|
|||
## Coding Conventions |
|||
- Lower-case single-word folder names |
|||
- Upper-case single-word file names |
|||
- Upper-case exports IF export is an object or reference |
|||
- Lower-case exports IF export is a function |
|||
|
|||
## Testing Scripts |
|||
- "npm run **test**": run all tests with minimal console output |
|||
- "npm run **testVerbose**": run all tests with all console output |
|||
- "npm run **testCoverage**": produce coverage report for all project code |
|||
- "npm run **testActionCreators**": only test action creators |
|||
- "npm run **testApp**": only test app screens and components |
|||
- "npm run **testMigrations**": only test database migrations |
|||
- "npm run **testRepos**": only test database repositories |
|||
- "npm run **testDB**": only test database setup and API calls |
|||
- "npm run **testNav**": only test navigation |
|||
- "npm run **testThemes**": only test app theming and styles setup |
|||
- "npm run **testServices**": only test app services |
@ -0,0 +1,16 @@ |
|||
import React from "react"; |
|||
import { View } from "react-native"; |
|||
|
|||
function MaterialIcon (props) { |
|||
function loadFont(){ |
|||
return true; |
|||
} |
|||
|
|||
return ( |
|||
<View> |
|||
|
|||
</View> |
|||
) |
|||
} |
|||
|
|||
export default MaterialIcon; |
@ -1,135 +0,0 @@ |
|||
// https://github.com/realm/realm-js/issues/370#issuecomment-270849466
|
|||
export default class MockRealm { |
|||
constructor(params) { |
|||
this.schema = {}; |
|||
this.schemaVersion = params.schemaVersion; |
|||
this.callbackList = []; |
|||
this.data = {}; |
|||
this.schemaCallbackList = {}; |
|||
params.schema.forEach((schema) => { |
|||
this.data[schema.name] = {}; |
|||
}); |
|||
params.schema.forEach((schema) => { |
|||
this.schema[schema.name] = schema; |
|||
}); |
|||
this.lastLookedUpModel = null; |
|||
} |
|||
|
|||
objects(schemaName) { |
|||
this.lastLookedUpModel = schemaName; |
|||
const objects = Object.values(this.data[schemaName]); |
|||
objects.values = () => objects; |
|||
objects.sorted = () => this.compareFunc ? objects.sort(this.compareFunc) : objects.sort(); |
|||
objects.addListener = (cb) => { |
|||
if (this.schemaCallbackList[schemaName]) { |
|||
this.schemaCallbackList[schemaName].push(cb); |
|||
} else { |
|||
this.schemaCallbackList[schemaName] = [cb]; |
|||
} |
|||
}; |
|||
objects.removeListener = () => {}; |
|||
objects.filtered = this.filtered ? this.filtered.bind(this, schemaName) : () => objects; |
|||
return objects; |
|||
} |
|||
|
|||
write(fn) { |
|||
this.writing = true; |
|||
fn(); |
|||
this.writing = false; |
|||
} |
|||
|
|||
create(schemaName, object) { |
|||
const modelObject = object; |
|||
const properties = this.schema[schemaName].schema.properties; |
|||
Object.keys(properties).forEach((key) => { |
|||
if (modelObject[key] && modelObject[key].model) { |
|||
this.data[modelObject[key].model][modelObject[key].id] = this.create( |
|||
modelObject[key].model, modelObject[key], |
|||
); |
|||
} else if (modelObject[key] && modelObject[key].length && modelObject[key][0].model) { |
|||
modelObject[key].forEach((obj) => { |
|||
this.data[modelObject[key][0].model][obj.id] = obj; |
|||
}); |
|||
modelObject[key].filtered = this.filtered ? this.filtered : () => modelObject[key]; |
|||
modelObject[key].sorted = () => modelObject[key].sort(); |
|||
} else if (modelObject[key] === undefined) { |
|||
if (typeof properties[key] === 'object' && properties[key].optional) { |
|||
modelObject[key] = null; |
|||
} |
|||
if (typeof properties[key] === 'object' && ['list', 'linkingObjects'].includes(properties[key].type)) { |
|||
modelObject[key] = []; |
|||
modelObject[key].filtered = () => []; |
|||
modelObject[key].sorted = () => []; |
|||
} |
|||
} |
|||
}); |
|||
|
|||
this.data[schemaName][modelObject.id] = modelObject; |
|||
if (this.writing) { |
|||
if (this.schemaCallbackList[schemaName]) { |
|||
this.schemaCallbackList[schemaName].forEach(cb => cb(schemaName, { |
|||
insertions: { length: 1 }, |
|||
modifications: { length: 0 }, |
|||
deletions: { length: 0 }, |
|||
})); |
|||
} |
|||
this.callbackList.forEach((cb) => { cb(); }); |
|||
} |
|||
return modelObject; |
|||
} |
|||
|
|||
objectForPrimaryKey(model, id) { |
|||
this.lastLookedUpModel = model; |
|||
return this.data[model][id]; |
|||
} |
|||
|
|||
delete(object) { |
|||
if (this.lastLookedUpModel || object.model) { |
|||
const model = object.model ? object.model : this.lastLookedUpModel |
|||
if (Array.isArray(object)) { |
|||
object.forEach((item) => { |
|||
delete this.data[model][item.id]; |
|||
}); |
|||
} |
|||
delete this.data[model][object.id]; |
|||
if (this.writing) { |
|||
if (this.schemaCallbackList[model]) { |
|||
this.schemaCallbackList[model].forEach(cb => cb(model, { |
|||
insertions: { length: 0 }, |
|||
modifications: { length: 0 }, |
|||
deletions: { length: 1 }, |
|||
})); |
|||
} |
|||
this.callbackList.forEach((cb) => { cb(); }); |
|||
} |
|||
} |
|||
} |
|||
|
|||
deleteAll() { |
|||
Object.keys(this.schema).forEach((key) => { |
|||
if (this.writing && this.schemaCallbackList[this.schema[key].name]) { |
|||
this.schemaCallbackList[this.schema[key].name].forEach(cb => cb(key, { |
|||
insertions: { length: 0 }, |
|||
modifications: { length: 0 }, |
|||
deletions: { length: Object.values(this.data[this.schema[key].name]).length }, |
|||
})); |
|||
} |
|||
this.data[this.schema[key].name] = {}; |
|||
}); |
|||
if (this.writing) this.callbackList.forEach((cb) => { cb(); }); |
|||
} |
|||
|
|||
addListener(event, callback) { |
|||
this.callbackList.push(callback); |
|||
} |
|||
|
|||
prepareData(schemaName, objects) { |
|||
objects.forEach((object) => { |
|||
this.create(schemaName, object); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
MockRealm.Object = class Object { |
|||
isValid() { return true; } |
|||
}; |
@ -1,6 +1,6 @@ |
|||
import { squareRef, navigate } from "../src/navigation/SquareNav"; |
|||
import { squareRef, squareNav } from "../src/navigation/SquareNav"; |
|||
|
|||
test('SquareNav calls navigation ref', () => { |
|||
let postNav = navigate('notascreen', {}); |
|||
let postNav = squareNav('notascreen', {}); |
|||
expect(postNav).toEqual(true); |
|||
}); |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 849 B |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 702 B |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 942 B |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.7 KiB |
@ -0,0 +1,604 @@ |
|||
PODS: |
|||
- boost (1.76.0) |
|||
- CocoaAsyncSocket (7.6.5) |
|||
- DoubleConversion (1.1.6) |
|||
- FBLazyVector (0.69.2) |
|||
- FBReactNativeSpec (0.69.2): |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- RCTRequired (= 0.69.2) |
|||
- RCTTypeSafety (= 0.69.2) |
|||
- React-Core (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- Flipper (0.125.0): |
|||
- Flipper-Folly (~> 2.6) |
|||
- Flipper-RSocket (~> 1.4) |
|||
- Flipper-Boost-iOSX (1.76.0.1.11) |
|||
- Flipper-DoubleConversion (3.2.0.1) |
|||
- Flipper-Fmt (7.1.7) |
|||
- Flipper-Folly (2.6.10): |
|||
- Flipper-Boost-iOSX |
|||
- Flipper-DoubleConversion |
|||
- Flipper-Fmt (= 7.1.7) |
|||
- Flipper-Glog |
|||
- libevent (~> 2.1.12) |
|||
- OpenSSL-Universal (= 1.1.1100) |
|||
- Flipper-Glog (0.5.0.5) |
|||
- Flipper-PeerTalk (0.0.4) |
|||
- Flipper-RSocket (1.4.3): |
|||
- Flipper-Folly (~> 2.6) |
|||
- FlipperKit (0.125.0): |
|||
- FlipperKit/Core (= 0.125.0) |
|||
- FlipperKit/Core (0.125.0): |
|||
- Flipper (~> 0.125.0) |
|||
- FlipperKit/CppBridge |
|||
- FlipperKit/FBCxxFollyDynamicConvert |
|||
- FlipperKit/FBDefines |
|||
- FlipperKit/FKPortForwarding |
|||
- SocketRocket (~> 0.6.0) |
|||
- FlipperKit/CppBridge (0.125.0): |
|||
- Flipper (~> 0.125.0) |
|||
- FlipperKit/FBCxxFollyDynamicConvert (0.125.0): |
|||
- Flipper-Folly (~> 2.6) |
|||
- FlipperKit/FBDefines (0.125.0) |
|||
- FlipperKit/FKPortForwarding (0.125.0): |
|||
- CocoaAsyncSocket (~> 7.6) |
|||
- Flipper-PeerTalk (~> 0.0.4) |
|||
- FlipperKit/FlipperKitHighlightOverlay (0.125.0) |
|||
- FlipperKit/FlipperKitLayoutHelpers (0.125.0): |
|||
- FlipperKit/Core |
|||
- FlipperKit/FlipperKitHighlightOverlay |
|||
- FlipperKit/FlipperKitLayoutTextSearchable |
|||
- FlipperKit/FlipperKitLayoutIOSDescriptors (0.125.0): |
|||
- FlipperKit/Core |
|||
- FlipperKit/FlipperKitHighlightOverlay |
|||
- FlipperKit/FlipperKitLayoutHelpers |
|||
- YogaKit (~> 1.18) |
|||
- FlipperKit/FlipperKitLayoutPlugin (0.125.0): |
|||
- FlipperKit/Core |
|||
- FlipperKit/FlipperKitHighlightOverlay |
|||
- FlipperKit/FlipperKitLayoutHelpers |
|||
- FlipperKit/FlipperKitLayoutIOSDescriptors |
|||
- FlipperKit/FlipperKitLayoutTextSearchable |
|||
- YogaKit (~> 1.18) |
|||
- FlipperKit/FlipperKitLayoutTextSearchable (0.125.0) |
|||
- FlipperKit/FlipperKitNetworkPlugin (0.125.0): |
|||
- FlipperKit/Core |
|||
- FlipperKit/FlipperKitReactPlugin (0.125.0): |
|||
- FlipperKit/Core |
|||
- FlipperKit/FlipperKitUserDefaultsPlugin (0.125.0): |
|||
- FlipperKit/Core |
|||
- FlipperKit/SKIOSNetworkPlugin (0.125.0): |
|||
- FlipperKit/Core |
|||
- FlipperKit/FlipperKitNetworkPlugin |
|||
- fmt (6.2.1) |
|||
- GCDWebServer (3.5.4): |
|||
- GCDWebServer/Core (= 3.5.4) |
|||
- GCDWebServer/Core (3.5.4) |
|||
- glog (0.3.5) |
|||
- libevent (2.1.12) |
|||
- OpenSSL-Universal (1.1.1100) |
|||
- RCT-Folly (2021.06.28.00-v2): |
|||
- boost |
|||
- DoubleConversion |
|||
- fmt (~> 6.2.1) |
|||
- glog |
|||
- RCT-Folly/Default (= 2021.06.28.00-v2) |
|||
- RCT-Folly/Default (2021.06.28.00-v2): |
|||
- boost |
|||
- DoubleConversion |
|||
- fmt (~> 6.2.1) |
|||
- glog |
|||
- RCTRequired (0.69.2) |
|||
- RCTTypeSafety (0.69.2): |
|||
- FBLazyVector (= 0.69.2) |
|||
- RCTRequired (= 0.69.2) |
|||
- React-Core (= 0.69.2) |
|||
- React (0.69.2): |
|||
- React-Core (= 0.69.2) |
|||
- React-Core/DevSupport (= 0.69.2) |
|||
- React-Core/RCTWebSocket (= 0.69.2) |
|||
- React-RCTActionSheet (= 0.69.2) |
|||
- React-RCTAnimation (= 0.69.2) |
|||
- React-RCTBlob (= 0.69.2) |
|||
- React-RCTImage (= 0.69.2) |
|||
- React-RCTLinking (= 0.69.2) |
|||
- React-RCTNetwork (= 0.69.2) |
|||
- React-RCTSettings (= 0.69.2) |
|||
- React-RCTText (= 0.69.2) |
|||
- React-RCTVibration (= 0.69.2) |
|||
- React-bridging (0.69.2): |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-callinvoker (0.69.2) |
|||
- React-Codegen (0.69.2): |
|||
- FBReactNativeSpec (= 0.69.2) |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- RCTRequired (= 0.69.2) |
|||
- RCTTypeSafety (= 0.69.2) |
|||
- React-Core (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- React-Core (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default (= 0.69.2) |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/CoreModulesHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/Default (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/DevSupport (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default (= 0.69.2) |
|||
- React-Core/RCTWebSocket (= 0.69.2) |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-jsinspector (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTActionSheetHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTAnimationHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTBlobHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTImageHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTLinkingHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTNetworkHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTSettingsHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTTextHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTVibrationHeaders (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-Core/RCTWebSocket (0.69.2): |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Core/Default (= 0.69.2) |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsiexecutor (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- Yoga |
|||
- React-CoreModules (0.69.2): |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- RCTTypeSafety (= 0.69.2) |
|||
- React-Codegen (= 0.69.2) |
|||
- React-Core/CoreModulesHeaders (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-RCTImage (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- React-cxxreact (0.69.2): |
|||
- boost (= 1.76.0) |
|||
- DoubleConversion |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-callinvoker (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-jsinspector (= 0.69.2) |
|||
- React-logger (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- React-runtimeexecutor (= 0.69.2) |
|||
- React-jsi (0.69.2): |
|||
- boost (= 1.76.0) |
|||
- DoubleConversion |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-jsi/Default (= 0.69.2) |
|||
- React-jsi/Default (0.69.2): |
|||
- boost (= 1.76.0) |
|||
- DoubleConversion |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-jsiexecutor (0.69.2): |
|||
- DoubleConversion |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- React-jsinspector (0.69.2) |
|||
- React-logger (0.69.2): |
|||
- glog |
|||
- react-native-get-random-values (1.8.0): |
|||
- React-Core |
|||
- react-native-safe-area-context (4.3.1): |
|||
- RCT-Folly |
|||
- RCTRequired |
|||
- RCTTypeSafety |
|||
- React |
|||
- ReactCommon/turbomodule/core |
|||
- React-perflogger (0.69.2) |
|||
- React-RCTActionSheet (0.69.2): |
|||
- React-Core/RCTActionSheetHeaders (= 0.69.2) |
|||
- React-RCTAnimation (0.69.2): |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- RCTTypeSafety (= 0.69.2) |
|||
- React-Codegen (= 0.69.2) |
|||
- React-Core/RCTAnimationHeaders (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- React-RCTBlob (0.69.2): |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Codegen (= 0.69.2) |
|||
- React-Core/RCTBlobHeaders (= 0.69.2) |
|||
- React-Core/RCTWebSocket (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-RCTNetwork (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- React-RCTImage (0.69.2): |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- RCTTypeSafety (= 0.69.2) |
|||
- React-Codegen (= 0.69.2) |
|||
- React-Core/RCTImageHeaders (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-RCTNetwork (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- React-RCTLinking (0.69.2): |
|||
- React-Codegen (= 0.69.2) |
|||
- React-Core/RCTLinkingHeaders (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- React-RCTNetwork (0.69.2): |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- RCTTypeSafety (= 0.69.2) |
|||
- React-Codegen (= 0.69.2) |
|||
- React-Core/RCTNetworkHeaders (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- React-RCTSettings (0.69.2): |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- RCTTypeSafety (= 0.69.2) |
|||
- React-Codegen (= 0.69.2) |
|||
- React-Core/RCTSettingsHeaders (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- React-RCTText (0.69.2): |
|||
- React-Core/RCTTextHeaders (= 0.69.2) |
|||
- React-RCTVibration (0.69.2): |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-Codegen (= 0.69.2) |
|||
- React-Core/RCTVibrationHeaders (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (= 0.69.2) |
|||
- React-runtimeexecutor (0.69.2): |
|||
- React-jsi (= 0.69.2) |
|||
- ReactCommon/turbomodule/core (0.69.2): |
|||
- DoubleConversion |
|||
- glog |
|||
- RCT-Folly (= 2021.06.28.00-v2) |
|||
- React-bridging (= 0.69.2) |
|||
- React-callinvoker (= 0.69.2) |
|||
- React-Core (= 0.69.2) |
|||
- React-cxxreact (= 0.69.2) |
|||
- React-jsi (= 0.69.2) |
|||
- React-logger (= 0.69.2) |
|||
- React-perflogger (= 0.69.2) |
|||
- RealmJS (10.19.5): |
|||
- GCDWebServer |
|||
- React |
|||
- RNGestureHandler (2.5.0): |
|||
- React-Core |
|||
- RNKeychain (8.1.1): |
|||
- React-Core |
|||
- RNScreens (3.15.0): |
|||
- React-Core |
|||
- React-RCTImage |
|||
- RNVectorIcons (9.2.0): |
|||
- React-Core |
|||
- SocketRocket (0.6.0) |
|||
- Yoga (1.14.0) |
|||
- YogaKit (1.18.1): |
|||
- Yoga (~> 1.14) |
|||
|
|||
DEPENDENCIES: |
|||
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) |
|||
- 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/React/FBReactNativeSpec`) |
|||
- Flipper (= 0.125.0) |
|||
- Flipper-Boost-iOSX (= 1.76.0.1.11) |
|||
- Flipper-DoubleConversion (= 3.2.0.1) |
|||
- Flipper-Fmt (= 7.1.7) |
|||
- Flipper-Folly (= 2.6.10) |
|||
- Flipper-Glog (= 0.5.0.5) |
|||
- Flipper-PeerTalk (= 0.0.4) |
|||
- Flipper-RSocket (= 1.4.3) |
|||
- FlipperKit (= 0.125.0) |
|||
- FlipperKit/Core (= 0.125.0) |
|||
- FlipperKit/CppBridge (= 0.125.0) |
|||
- FlipperKit/FBCxxFollyDynamicConvert (= 0.125.0) |
|||
- FlipperKit/FBDefines (= 0.125.0) |
|||
- FlipperKit/FKPortForwarding (= 0.125.0) |
|||
- FlipperKit/FlipperKitHighlightOverlay (= 0.125.0) |
|||
- FlipperKit/FlipperKitLayoutPlugin (= 0.125.0) |
|||
- FlipperKit/FlipperKitLayoutTextSearchable (= 0.125.0) |
|||
- FlipperKit/FlipperKitNetworkPlugin (= 0.125.0) |
|||
- FlipperKit/FlipperKitReactPlugin (= 0.125.0) |
|||
- FlipperKit/FlipperKitUserDefaultsPlugin (= 0.125.0) |
|||
- FlipperKit/SKIOSNetworkPlugin (= 0.125.0) |
|||
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) |
|||
- OpenSSL-Universal (= 1.1.1100) |
|||
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) |
|||
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) |
|||
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) |
|||
- React (from `../node_modules/react-native/`) |
|||
- React-bridging (from `../node_modules/react-native/ReactCommon`) |
|||
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) |
|||
- React-Codegen (from `build/generated/ios`) |
|||
- 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-logger (from `../node_modules/react-native/ReactCommon/logger`) |
|||
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`) |
|||
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) |
|||
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) |
|||
- 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`) |
|||
- React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) |
|||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) |
|||
- RealmJS (from `../node_modules/realm`) |
|||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`) |
|||
- RNKeychain (from `../node_modules/react-native-keychain`) |
|||
- RNScreens (from `../node_modules/react-native-screens`) |
|||
- RNVectorIcons (from `../node_modules/react-native-vector-icons`) |
|||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`) |
|||
|
|||
SPEC REPOS: |
|||
trunk: |
|||
- CocoaAsyncSocket |
|||
- Flipper |
|||
- Flipper-Boost-iOSX |
|||
- Flipper-DoubleConversion |
|||
- Flipper-Fmt |
|||
- Flipper-Folly |
|||
- Flipper-Glog |
|||
- Flipper-PeerTalk |
|||
- Flipper-RSocket |
|||
- FlipperKit |
|||
- fmt |
|||
- GCDWebServer |
|||
- libevent |
|||
- OpenSSL-Universal |
|||
- SocketRocket |
|||
- YogaKit |
|||
|
|||
EXTERNAL SOURCES: |
|||
boost: |
|||
:podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" |
|||
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/React/FBReactNativeSpec" |
|||
glog: |
|||
:podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" |
|||
RCT-Folly: |
|||
:podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" |
|||
RCTRequired: |
|||
:path: "../node_modules/react-native/Libraries/RCTRequired" |
|||
RCTTypeSafety: |
|||
:path: "../node_modules/react-native/Libraries/TypeSafety" |
|||
React: |
|||
:path: "../node_modules/react-native/" |
|||
React-bridging: |
|||
:path: "../node_modules/react-native/ReactCommon" |
|||
React-callinvoker: |
|||
:path: "../node_modules/react-native/ReactCommon/callinvoker" |
|||
React-Codegen: |
|||
:path: build/generated/ios |
|||
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-logger: |
|||
:path: "../node_modules/react-native/ReactCommon/logger" |
|||
react-native-get-random-values: |
|||
:path: "../node_modules/react-native-get-random-values" |
|||
react-native-safe-area-context: |
|||
:path: "../node_modules/react-native-safe-area-context" |
|||
React-perflogger: |
|||
:path: "../node_modules/react-native/ReactCommon/reactperflogger" |
|||
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" |
|||
React-runtimeexecutor: |
|||
:path: "../node_modules/react-native/ReactCommon/runtimeexecutor" |
|||
ReactCommon: |
|||
:path: "../node_modules/react-native/ReactCommon" |
|||
RealmJS: |
|||
:path: "../node_modules/realm" |
|||
RNGestureHandler: |
|||
:path: "../node_modules/react-native-gesture-handler" |
|||
RNKeychain: |
|||
:path: "../node_modules/react-native-keychain" |
|||
RNScreens: |
|||
:path: "../node_modules/react-native-screens" |
|||
RNVectorIcons: |
|||
:path: "../node_modules/react-native-vector-icons" |
|||
Yoga: |
|||
:path: "../node_modules/react-native/ReactCommon/yoga" |
|||
|
|||
SPEC CHECKSUMS: |
|||
boost: a7c83b31436843459a1961bfd74b96033dc77234 |
|||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 |
|||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 |
|||
FBLazyVector: e3c1479be506060131807f2f2435af5107c58410 |
|||
FBReactNativeSpec: 1381e8c4230895b6c2d20cea6b216ac7096a95f0 |
|||
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0 |
|||
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c |
|||
Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 |
|||
Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b |
|||
Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 |
|||
Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 |
|||
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 |
|||
Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541 |
|||
FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86 |
|||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 |
|||
GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4 |
|||
glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a |
|||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 |
|||
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c |
|||
RCT-Folly: b9d9fe1fc70114b751c076104e52f3b1b5e5a95a |
|||
RCTRequired: b723d4d6da2795df58189a01f92856b6912cf256 |
|||
RCTTypeSafety: 3973d2fcf39f43f7819e840d56ea6b2fe45996a0 |
|||
React: 242d4ffb093ed57c4761307a69b23b2479930ae9 |
|||
React-bridging: 66938204bc9d703b9c357201a40bf498aeb14412 |
|||
React-callinvoker: bf0a87845bc3158eec32be848bd9546e79d6dd25 |
|||
React-Codegen: e5c04fc987e909433915f247699402ece1955aa0 |
|||
React-Core: 5acd5715010b56d23846859b3a68c316dad09d5b |
|||
React-CoreModules: 73db18e3aaf5e29f73e4b7c9ddf6ead823795d06 |
|||
React-cxxreact: 0fc57a199d2d69c0e0401c9eab944be9b972bf1b |
|||
React-jsi: f845df5e8fd5688cab3cdaaa06f5413e791a01bd |
|||
React-jsiexecutor: 7c23e92591431ac925f430b3118de934cb816ac0 |
|||
React-jsinspector: 31e53f048cc8f32605de36981903a7bbf9456892 |
|||
React-logger: 9a6c684d5cd56c4129e0c2842dba75c4bfb1e981 |
|||
react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a |
|||
react-native-safe-area-context: 6c12e3859b6f27b25de4fee8201cfb858432d8de |
|||
React-perflogger: 281c34e42f13245c7a4d6932364d9182f8655e1a |
|||
React-RCTActionSheet: 92f4292754a1b4a0e42bf9b1489206a06f878929 |
|||
React-RCTAnimation: 2a5bb5549758e4e594481633f3db649d11519f75 |
|||
React-RCTBlob: cf573ac95fc612ed4440cad0b92161722430de87 |
|||
React-RCTImage: af8b9a46a743937db396fcb43320f57b570661dc |
|||
React-RCTLinking: 81029ed5767d2a2c13c03caeed32f87b72e73838 |
|||
React-RCTNetwork: 24c2b13acdcd43af39b2da90584c92e7799ee366 |
|||
React-RCTSettings: 028b0e20ff60d2c7ba47cedec8e99e69b6691c40 |
|||
React-RCTText: 6d17c2aead07b9de7ddc8765b580d0fb4b1d2e50 |
|||
React-RCTVibration: 0d07f00705b5f11e88aaaaf9131f5e1785d4bd6e |
|||
React-runtimeexecutor: 8030b9cf9b9e87b878d92da680b55b5e74c58e70 |
|||
ReactCommon: a9414b91f0d19de002b55d9f4f6cb176d6dd8452 |
|||
RealmJS: 400aac2267a47b25fcc2b6321e8a419282719d16 |
|||
RNGestureHandler: bad495418bcbd3ab47017a38d93d290ebd406f50 |
|||
RNKeychain: ff836453cba46938e0e9e4c22e43d43fa2c90333 |
|||
RNScreens: 4a1af06327774490d97342c00aee0c2bafb497b7 |
|||
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8 |
|||
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 |
|||
Yoga: 236056dd74cda4d9d76c20306fd8c20bb087614d |
|||
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a |
|||
|
|||
PODFILE CHECKSUM: d581c290a90c94822dda89c7b1468491518584f1 |
|||
|
|||
COCOAPODS: 1.11.3 |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,25 @@ |
|||
import React from "react"; |
|||
import { Animated, Easing} from "react-native"; |
|||
import { useEffect, useRef } from "react"; |
|||
import Metrics from "../themes/Metrics"; |
|||
|
|||
function Autoscroll(props){ |
|||
const yPosition = useRef(new Animated.Value(props.origin)); |
|||
|
|||
useEffect(() => { |
|||
Animated.timing(yPosition.current, { |
|||
toValue: props.destination - Metrics.animated.gameScrollInterval, |
|||
duration: props.duration, |
|||
useNativeDriver: true |
|||
}).start(); |
|||
}, [props.origin]) |
|||
|
|||
|
|||
return ( |
|||
<Animated.View style={{ transform: [{ translateY: yPosition.current }]}}> |
|||
{props.children} |
|||
</Animated.View> |
|||
) |
|||
} |
|||
|
|||
export default Autoscroll; |
@ -0,0 +1,38 @@ |
|||
import React from "react"; |
|||
import { Animated} from "react-native"; |
|||
import { useEffect, useRef } from "react"; |
|||
|
|||
function Fade(props){ |
|||
const faded = useRef(new Animated.Value(0.1)); |
|||
|
|||
useEffect(() => { |
|||
if (props.faded) { |
|||
Animated.timing( |
|||
faded.current, |
|||
{ |
|||
toValue: 0.1, |
|||
duration: props.duration, |
|||
useNativeDriver: true |
|||
} |
|||
).start(); |
|||
} else { |
|||
Animated.timing( |
|||
faded.current, |
|||
{ |
|||
toValue: 1, |
|||
duration: props.duration, |
|||
useNativeDriver: true |
|||
} |
|||
).start(); |
|||
} |
|||
}, [props.faded]) |
|||
|
|||
|
|||
return ( |
|||
<Animated.View style={{ opacity: faded.current}}> |
|||
{props.children} |
|||
</Animated.View> |
|||
) |
|||
} |
|||
|
|||
export default Fade; |
@ -0,0 +1,47 @@ |
|||
import React from "react"; |
|||
import { Text, View } from "react-native"; |
|||
import { TouchableOpacity } from "react-native-gesture-handler"; |
|||
import { styles } from "../screens/styles/AppStyles"; |
|||
|
|||
function NineKey(props){ |
|||
|
|||
function generateKey(value){ |
|||
return ( |
|||
<TouchableOpacity |
|||
style={[styles.darkGreen, styles.nineKeyButton, styles.dropShadow, styles.centeredJustify]} |
|||
onPress={() => props.onPress(value)} |
|||
> |
|||
<Text style={[styles.boldText, styles.headerTitleFont, styles.centeredText, styles.lightText]}> |
|||
{value} |
|||
</Text> |
|||
</TouchableOpacity> |
|||
); |
|||
} |
|||
|
|||
return ( |
|||
<View style={[styles.centeredItems]}> |
|||
<View style={styles.flexRow}> |
|||
{generateKey(7)} |
|||
{generateKey(8)} |
|||
{generateKey(9)} |
|||
</View> |
|||
<View style={styles.flexRow}> |
|||
{generateKey(4)} |
|||
{generateKey(5)} |
|||
{generateKey(6)} |
|||
</View> |
|||
<View style={styles.flexRow}> |
|||
{generateKey(1)} |
|||
{generateKey(2)} |
|||
{generateKey(3)} |
|||
</View> |
|||
<View style={styles.flexRow}> |
|||
<View style={[styles.nineKeyButton]} /> |
|||
{generateKey(0)} |
|||
<View style={[styles.nineKeyButton]} /> |
|||
</View> |
|||
</View> |
|||
); |
|||
} |
|||
|
|||
export default NineKey; |
@ -0,0 +1,63 @@ |
|||
import React, { useRef, useState } from "react"; |
|||
import { |
|||
ScrollView, |
|||
Animated, |
|||
} from "react-native"; |
|||
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; |
|||
import Icons from '../themes/Icons'; |
|||
import Colors from "../themes/Colors"; |
|||
import Metrics from "../themes/Metrics"; |
|||
import { styles } from "../screens/styles/AppStyles"; |
|||
import Fade from "./Fade"; |
|||
|
|||
function ScrollingPicker(props) { |
|||
const scrollX = useRef(new Animated.Value(0)).current; |
|||
|
|||
function onScroll(event){ |
|||
let rounded = Math.round(event.nativeEvent.contentOffset.x); |
|||
if (rounded === 0) { |
|||
props.modeSetter('square'); |
|||
} else if (rounded === (Metrics.icons.buttonIcon * 2)) { |
|||
props.modeSetter('addition'); |
|||
} |
|||
Animated.event([ |
|||
{ |
|||
nativeEvent: { |
|||
contentOffset: { |
|||
x: scrollX |
|||
} |
|||
} |
|||
} |
|||
], {useNativeDriver: true}) |
|||
} |
|||
|
|||
return ( |
|||
<ScrollView |
|||
horizontal={true} |
|||
pagingEnabled={true} |
|||
showsHorizontalScrollIndicator={false} |
|||
style={styles.modePicker} |
|||
onScroll={onScroll} |
|||
scrollEventThrottle={0} |
|||
> |
|||
<Fade faded={props.mode !== 'square'} duration={250}> |
|||
<MaterialIcon |
|||
name={Icons.squareIcons.square} |
|||
color={Colors.material.dark} |
|||
size={Metrics.icons.buttonIcon} |
|||
style={styles.modePickerMargin} |
|||
/> |
|||
</Fade> |
|||
<Fade faded={props.mode !== 'addition'} duration={250}> |
|||
<MaterialIcon |
|||
name={Icons.squareIcons.plus} |
|||
color={Colors.material.dark} |
|||
size={Metrics.icons.buttonIcon} |
|||
style={styles.modePickerMargin} |
|||
/> |
|||
</Fade> |
|||
</ScrollView> |
|||
); |
|||
} |
|||
|
|||
export default ScrollingPicker; |
@ -0,0 +1,27 @@ |
|||
import React from "react"; |
|||
import { Animated, Easing} from "react-native"; |
|||
import { useEffect, useState } from "react"; |
|||
|
|||
function Slider(props){ |
|||
const [xPosition, setXPosition] = useState(new Animated.Value(props.origin)); |
|||
|
|||
useEffect(() => { |
|||
Animated.sequence([ |
|||
Animated.delay(props.delay), |
|||
Animated.timing(xPosition, { |
|||
toValue: 0, |
|||
duration: props.duration, |
|||
useNativeDriver: true |
|||
}) |
|||
]).start(); |
|||
}, []); |
|||
|
|||
|
|||
return ( |
|||
<Animated.View style={{ transform: [{ translateX: xPosition }]}}> |
|||
{props.children} |
|||
</Animated.View> |
|||
) |
|||
} |
|||
|
|||
export default Slider; |
@ -0,0 +1,39 @@ |
|||
import React from "react"; |
|||
import { Animated, Easing} from "react-native"; |
|||
import { useEffect } from "react"; |
|||
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; |
|||
import Icons from '../themes/Icons'; |
|||
import Colors from "../themes/Colors"; |
|||
import Metrics from "../themes/Metrics"; |
|||
|
|||
const spinValue = new Animated.Value(0); |
|||
|
|||
function Spinner(){ |
|||
|
|||
useEffect(() => { |
|||
Animated.loop( |
|||
Animated.timing(spinValue, { |
|||
toValue: 1, |
|||
duration: 3000, |
|||
easing: Easing.linear, |
|||
useNativeDriver: true, |
|||
})).start(); |
|||
}, []); |
|||
|
|||
const spin = spinValue.interpolate({ |
|||
inputRange: [0, 1], |
|||
outputRange: ['0deg', '360deg'], |
|||
}); |
|||
|
|||
return ( |
|||
<Animated.View style={{ transform: [{ rotate: spin }]}}> |
|||
<MaterialIcon |
|||
name={Icons.squareIcons.square} |
|||
color={Colors.material.green800} |
|||
size={Metrics.icons.splashIcon} |
|||
/> |
|||
</Animated.View> |
|||
) |
|||
} |
|||
|
|||
export default Spinner; |
@ -0,0 +1,6 @@ |
|||
export function calculateSquareScore (answers, finalTime) { |
|||
let timeScore = Math.round((60 - finalTime) * 1000); |
|||
let answerScore = answers * 1000; |
|||
let finalScore = timeScore + answerScore; |
|||
return finalScore; |
|||
} |
@ -1,13 +1,57 @@ |
|||
import 'react-native-get-random-values'; |
|||
|
|||
export function generateKey() { |
|||
let result = []; |
|||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; |
|||
let charactersLength = characters.length; |
|||
|
|||
let uintArray = new Uint8Array(64); |
|||
let newKey = crypto.getRandomValues(uintArray); |
|||
|
|||
for (let i = 0; i < 64; i++) { |
|||
let newCharIndex = newKey[i]; |
|||
while(newCharIndex > charactersLength){ |
|||
newCharIndex -= charactersLength; |
|||
} |
|||
result.push( |
|||
characters.charAt(Math.floor(Math.random() * charactersLength)), |
|||
characters.charAt(newCharIndex), |
|||
); |
|||
} |
|||
|
|||
return result.join(''); |
|||
} |
|||
|
|||
export function genSquareChallenge(){ |
|||
let result = []; |
|||
let uintArray = new Uint8Array(20); |
|||
let squares = crypto.getRandomValues(uintArray); |
|||
let shapes = crypto.getRandomValues(uintArray); |
|||
|
|||
for(let i = 0; i < 20; ++i){ |
|||
let squarePos = squares[i] % 2; |
|||
let shapeType = shapes[i] % 6; |
|||
result.push({ |
|||
squarePos: squarePos, |
|||
shapeType: shapeType |
|||
}); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
export function generateAdditionChallenge(){ |
|||
let result = []; |
|||
for (let i = 0; i < 20; ++i) { |
|||
let left = 0; |
|||
let right = 0; |
|||
|
|||
do { |
|||
left = Math.round(Math.random() * 10); |
|||
right = Math.round(Math.random() * 10); |
|||
} while (left + right >= 10); |
|||
|
|||
result.push({left: left, right: right}); |
|||
} |
|||
|
|||
return result; |
|||
} |
@ -0,0 +1,10 @@ |
|||
import Icons from "../themes/Icons"; |
|||
|
|||
export const shapes = { |
|||
'0': Icons.wrongShapes.rectangle, |
|||
'1': Icons.wrongShapes.triangle, |
|||
'2': Icons.wrongShapes.circle, |
|||
'3': Icons.wrongShapes.hexagon, |
|||
'4': Icons.wrongShapes.pentagon, |
|||
'5': Icons.wrongShapes.octagon |
|||
} |
@ -1,8 +1,8 @@ |
|||
import { createRef } from "react"; |
|||
|
|||
export const squareRef = createRef(); |
|||
export const SquareRef = createRef(); |
|||
|
|||
export function navigate(name, params) { |
|||
squareRef.current?.navigate(name, params); |
|||
export function squareNav(name, params) { |
|||
SquareRef.current?.navigate(name, params); |
|||
return true; |
|||
} |
@ -0,0 +1,48 @@ |
|||
import {initDB} from './DbInit'; |
|||
|
|||
class DatabaseAPI { |
|||
constructor(){ |
|||
this.systemRepo = null; |
|||
this.scoreRepo = null; |
|||
this.userRepo = null; |
|||
} |
|||
|
|||
getAllSystemValues() { |
|||
return this.systemRepo.getAllSystemValues(); |
|||
} |
|||
|
|||
createSystemValue(key, value) { |
|||
this.systemRepo.createSystemValue(key, value); |
|||
return true; |
|||
} |
|||
|
|||
deleteSystemValue(key) { |
|||
this.systemRepo.deleteSystemValue(key); |
|||
return true; |
|||
} |
|||
|
|||
getSystemValue(key) { |
|||
return this.systemRepo.getSystemKeyValue(key); |
|||
} |
|||
|
|||
createScore(user, score) { |
|||
this.scoreRepo.createScore(user, score); |
|||
return true; |
|||
} |
|||
|
|||
getHighScores() { |
|||
return this.scoreRepo.getCachedScores(); |
|||
} |
|||
|
|||
async initDB() { |
|||
let repos = await initDB(); |
|||
this.systemRepo = repos.systemRepo; |
|||
this.scoreRepo = repos.scoreRepo; |
|||
this.userRepo = repos.userRepo; |
|||
|
|||
this.scoreRepo.loadCache(); |
|||
} |
|||
} |
|||
|
|||
const DbAPI = new DatabaseAPI(); |
|||
export default DbAPI; |
@ -1,37 +0,0 @@ |
|||
import {initDB} from './dbInit'; |
|||
|
|||
class DbAPI { |
|||
constructor(){ |
|||
this.systemRepo = null; |
|||
this.scoreRepo = null; |
|||
this.userRepo = null; |
|||
} |
|||
|
|||
getAllSystemValues() { |
|||
return systemRepo.getAllSystemValues(); |
|||
} |
|||
|
|||
createSystemValue(key, value) { |
|||
systemRepo.createSystemValue(key, value); |
|||
return true; |
|||
} |
|||
|
|||
deleteSystemValue(key) { |
|||
systemRepo.deleteSystemValue(key); |
|||
return true; |
|||
} |
|||
|
|||
getSystemValue(key) { |
|||
return systemRepo.getSystemKeyValue(key); |
|||
} |
|||
|
|||
async initDB() { |
|||
let repos = await initDB(); |
|||
this.systemRepo = repos.systemRepo; |
|||
this.scoreRepo = repos.scoreRepo; |
|||
this.userRepo = repos.userRepo; |
|||
} |
|||
} |
|||
|
|||
const dbAPI = new DbAPI(); |
|||
export default dbAPI; |
@ -1,8 +1,8 @@ |
|||
import { configureStore } from '@reduxjs/toolkit'; |
|||
import rootReducer from './reducers/RootReducer'; |
|||
|
|||
const configStore = configureStore({ |
|||
const ConfigStore = configureStore({ |
|||
reducer: rootReducer |
|||
}); |
|||
|
|||
export default configStore; |
|||
export default ConfigStore; |
@ -1,21 +1,41 @@ |
|||
import { initDB } from "../../realm/dbInit"; |
|||
import dbAPI from "../../realm/dbAPI"; |
|||
import { APP_INIT } from "../types/SystemTypes"; |
|||
import DbAPI from "../../realm/DbAPI"; |
|||
import { APP_INIT, NAV_HOME, NAV_SCORES } from "../types/SystemTypes"; |
|||
import { squareNav } from "../../navigation/SquareNav"; |
|||
|
|||
export function appInit() { |
|||
return async (dispatch) => { |
|||
await dbAPI.initDB(); |
|||
dispatch(onInit()); |
|||
await DbAPI.initDB(); |
|||
let lastUsername = DbAPI.getSystemValue('username').value; |
|||
dispatch(onInit(lastUsername)); |
|||
squareNav('Home'); |
|||
} |
|||
} |
|||
|
|||
function onInit() { |
|||
export function goHome() { |
|||
return (dispatch) => { |
|||
squareNav('Home'); |
|||
dispatch({ |
|||
type: APP_INIT |
|||
//system: system
|
|||
//user: user
|
|||
//score: score
|
|||
type: NAV_HOME |
|||
}) |
|||
} |
|||
} |
|||
|
|||
export function goToScores() { |
|||
return (dispatch) => { |
|||
squareNav('HighScore'); |
|||
dispatch({ |
|||
type: NAV_SCORES |
|||
}) |
|||
} |
|||
} |
|||
|
|||
function onInit(lastUsername) { |
|||
return (dispatch, getState) => { |
|||
let currentUser = {...getState().user}; |
|||
currentUser.username = lastUsername; |
|||
dispatch({ |
|||
type: APP_INIT, |
|||
user: currentUser |
|||
}); |
|||
} |
|||
} |
@ -0,0 +1,59 @@ |
|||
import { squareNav } from "../../navigation/SquareNav"; |
|||
import { ADDITION_FINISHED, ADDITION_START, SQUARE_FINISHED, SQUARE_START } from "../types/UserTypes"; |
|||
import { calculateSquareScore } from "../../libs/CalculateScore"; |
|||
import DbAPI from "../../realm/DbAPI"; |
|||
|
|||
export function squareStartPressed(mode, username) { |
|||
return (dispatch, getState) => { |
|||
DbAPI.createSystemValue('username', username); |
|||
let userState = {...getState().user}; |
|||
userState.username = username; |
|||
if (mode === 'square') { |
|||
squareNav('Game'); |
|||
dispatch({ |
|||
type: SQUARE_START, |
|||
user: userState |
|||
}); |
|||
} else if (mode === 'addition') { |
|||
squareNav('AdditionGame'); |
|||
dispatch({ |
|||
type: ADDITION_START, |
|||
user: userState |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
|
|||
export function squareFinished(answers, finalTime) { |
|||
return (dispatch, getState) => { |
|||
setTimeout(() => squareNav('Score'), 3000); |
|||
const userState = getState().user; |
|||
let newUser = {...userState}; |
|||
newUser.lastGameTime = finalTime; |
|||
newUser.lastGameAnswers = answers; |
|||
|
|||
let finalScore = calculateSquareScore(answers, finalTime); |
|||
DbAPI.createScore(userState.username, finalScore); |
|||
dispatch({ |
|||
type: SQUARE_FINISHED, |
|||
user: newUser |
|||
}); |
|||
} |
|||
} |
|||
|
|||
export function addFinished(answers, finalTime) { |
|||
return (dispatch, getState) => { |
|||
setTimeout(() => squareNav('Score'), 3000); |
|||
const userState = getState().user; |
|||
let newUser = {...userState}; |
|||
newUser.lastGameTime = finalTime; |
|||
newUser.lastGameAnswers = answers; |
|||
|
|||
let finalScore = calculateSquareScore(answers, finalTime); |
|||
DbAPI.createScore(userState.username, finalScore); |
|||
dispatch({ |
|||
type: ADDITION_FINISHED, |
|||
user: newUser |
|||
}); |
|||
} |
|||
} |
@ -1,15 +0,0 @@ |
|||
import * as SquareNav from '../../navigation/SquareNav'; |
|||
|
|||
import { APP_INIT } from '../types/SystemTypes'; |
|||
|
|||
export function navReducer(state = {}, action){ |
|||
switch (action.type) { |
|||
case APP_INIT: |
|||
//SquareNav.navigate('Home');
|
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
return state; |
|||
} |
@ -1,10 +1,10 @@ |
|||
import { combineReducers } from 'redux'; |
|||
import { systemReducer } from './SystemReducer'; |
|||
import { navReducer } from './NavReducer'; |
|||
import { userReducer } from './UserReducer'; |
|||
|
|||
const rootReducer = combineReducers({ |
|||
...systemReducer, |
|||
navReducer |
|||
...userReducer |
|||
}); |
|||
|
|||
export default rootReducer; |
@ -0,0 +1,31 @@ |
|||
import { APP_INIT } from "../types/SystemTypes"; |
|||
import { |
|||
SQUARE_START, |
|||
SQUARE_FINISHED, |
|||
ADDITION_FINISHED, |
|||
ADDITION_START |
|||
} from '../types/UserTypes'; |
|||
|
|||
const initialUserState = { |
|||
lastGameTime: null, |
|||
lastGameAnswers: null, |
|||
lastGameScore: null, |
|||
username: 'noname' |
|||
} |
|||
|
|||
function usr(state = initialUserState, action) { |
|||
switch (action.type) { |
|||
case APP_INIT: |
|||
case SQUARE_START: |
|||
case ADDITION_START: |
|||
case SQUARE_FINISHED: |
|||
case ADDITION_FINISHED: |
|||
return {...state, ...action.user}; |
|||
default: |
|||
return state; |
|||
} |
|||
} |
|||
|
|||
export const userReducer = { |
|||
user: usr |
|||
}; |
@ -1 +1,3 @@ |
|||
export const APP_INIT = 'app-init'; |
|||
export const NAV_HOME = 'go-home'; |
|||
export const NAV_SCORES = 'nav-scores'; |
@ -0,0 +1,4 @@ |
|||
export const SQUARE_START = 'square-start'; |
|||
export const SQUARE_FINISHED = 'square-finished'; |
|||
export const ADDITION_START = 'addition-start'; |
|||
export const ADDITION_FINISHED = 'addition-finished'; |
@ -0,0 +1,171 @@ |
|||
import React from "react"; |
|||
import { Text, TouchableOpacity, View, SafeAreaView } from "react-native"; |
|||
import { useState, useEffect, useRef, useMemo } from "react"; |
|||
import { useDispatch } from "react-redux"; |
|||
import {generateAdditionChallenge} from '../libs/Random'; |
|||
import { styles } from "./styles/AppStyles"; |
|||
import NineKey from "../components/NineKey"; |
|||
import Autoscroll from "../components/Autoscroll"; |
|||
import Fade from "../components/Fade"; |
|||
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; |
|||
import Icons from '../themes/Icons'; |
|||
import Colors from "../themes/Colors"; |
|||
import Metrics from "../themes/Metrics"; |
|||
import { addFinished } from "../redux/actions/UserActions"; |
|||
|
|||
function AdditionGame(props){ |
|||
|
|||
const [addChallenge, setAddChallenge]= useState(() => {return generateAdditionChallenge()}); |
|||
const challengeState = useRef(-1); |
|||
const squareMemo = useMemo(renderPairs, [challengeState.current]); |
|||
const [timerState, setTimerState] = useState(0); |
|||
const localTimer = useRef(null); |
|||
const startTime = useRef(0); |
|||
const answers = useRef(0); |
|||
const [scrollOrigin, setScrollOrigin] = useState(0); |
|||
const scrollDestination = useRef(Metrics.animated.gameScrollInterval); |
|||
const [headerText, setHeaderText] = useState('Ready?'); |
|||
const [headerColor, setHeaderColor] = useState(styles.green); |
|||
const [headerTextColor, setHeaderTextColor] = useState(styles.darkText); |
|||
const dispatch = useDispatch(); |
|||
|
|||
useEffect(() => { |
|||
let headerTimeout = null; |
|||
|
|||
switch(timerState){ |
|||
case 0: |
|||
headerTimeout = setTimeout(() => { |
|||
setHeaderColor(styles.yellow); |
|||
setHeaderText('Set'); |
|||
setTimerState(1); |
|||
}, 1000); |
|||
break; |
|||
case 1: |
|||
headerTimeout = setTimeout(() => { |
|||
setHeaderColor(styles.red); |
|||
setHeaderTextColor(styles.lightText); |
|||
setHeaderText('Go!'); |
|||
challengeState.current = 0; |
|||
setTimerState(2); |
|||
}, 1000); |
|||
break; |
|||
case 2: |
|||
headerTimeout = setTimeout(() => { |
|||
setHeaderColor(styles.dark); |
|||
startTime.current = (Date.now()); |
|||
setHeaderText(0 + ' s'); |
|||
setTimerState(3); |
|||
}, 1000); |
|||
break; |
|||
case 3: |
|||
headerTimeout = setInterval(() => { |
|||
let elapsed = Math.round((Date.now() - startTime.current) / (1000)); |
|||
setHeaderText(elapsed + ' s'); |
|||
}, 1000); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
localTimer.current = headerTimeout; |
|||
|
|||
return () => { |
|||
clearTimeout(localTimer.current); |
|||
clearInterval(localTimer.current); |
|||
} |
|||
}, [timerState]); |
|||
|
|||
|
|||
|
|||
function selectAnswer(answer){ |
|||
let currentChallenge = addChallenge[challengeState.current]; |
|||
let outcome = ( |
|||
answer === ( |
|||
currentChallenge.left + currentChallenge.right |
|||
) |
|||
); |
|||
|
|||
if (outcome) { |
|||
answers.current = answers.current + 1; |
|||
} |
|||
|
|||
let newOrigin = scrollDestination.current; |
|||
let newDestination = scrollDestination.current - Metrics.animated.gameScrollInterval; |
|||
|
|||
scrollDestination.current = newDestination; |
|||
challengeState.current = challengeState.current + 1; |
|||
setScrollOrigin(newOrigin); |
|||
|
|||
if (challengeState.current >= 20) { |
|||
completeChallenge(); |
|||
} |
|||
} |
|||
|
|||
function completeChallenge(){ |
|||
let unformatted = (Date.now() - startTime.current) / (1000); |
|||
let finalTime = Number.parseFloat(unformatted).toFixed(3); |
|||
clearInterval(localTimer.current); |
|||
setHeaderColor(styles.darkGreen); |
|||
setHeaderText(finalTime + ' s'); |
|||
setTimerState(4); |
|||
dispatch(addFinished(answers.current, finalTime)); |
|||
} |
|||
|
|||
function generateLine(left, right, pairIndex) { |
|||
return ( |
|||
<Fade key={pairIndex} faded={challengeState.current !== pairIndex} duration={250}> |
|||
<View style={[styles.buttonMargin, styles.addQuestionHeight]}> |
|||
<Text style={[styles.headerTitleFont, styles.darkText, styles.centeredText]}> |
|||
{left + ' + ' + right + ' = '} |
|||
</Text> |
|||
</View> |
|||
</Fade> |
|||
); |
|||
} |
|||
|
|||
function renderPairs(){ |
|||
return addChallenge.map((pair, index) => { |
|||
return generateLine(pair.left, pair.right, index); |
|||
}); |
|||
} |
|||
|
|||
return ( |
|||
<SafeAreaView style={styles.flex}> |
|||
<View style={[styles.timerView, headerColor, styles.centeredJustify]}> |
|||
<Text style={[headerTextColor, styles.headerTitleFont, styles.centeredText]}> |
|||
{headerText} |
|||
</Text> |
|||
</View> |
|||
<View style={[styles.flex, styles.flexColumn]}> |
|||
<Autoscroll |
|||
origin={scrollOrigin} |
|||
destination={scrollDestination.current} |
|||
duration={250} |
|||
style={{overflow: 'hidden'}} |
|||
> |
|||
{squareMemo} |
|||
<Fade faded={challengeState.current < 20} duration={250}> |
|||
<View style={[styles.gameView, styles.flexRow, styles.spaceEvenly, styles.centeredItems]}> |
|||
<MaterialIcon |
|||
name={Icons.squareIcons.check} |
|||
color={Colors.material.green800} |
|||
size={Metrics.icons.buttonIcon} |
|||
/> |
|||
<Text style={[styles.headerTitleFont, styles.greyText]}> |
|||
Finish |
|||
</Text> |
|||
</View> |
|||
</Fade> |
|||
</Autoscroll> |
|||
</View> |
|||
<View style={[styles.timerView, styles.dark, styles.centeredJustify]}> |
|||
<Text style={[styles.lightText, styles.headerTitleFont, styles.centeredText]}> |
|||
{answers.current + ' / ' + addChallenge.length} |
|||
</Text> |
|||
</View> |
|||
<NineKey onPress={selectAnswer}/> |
|||
</SafeAreaView> |
|||
); |
|||
} |
|||
|
|||
export default AdditionGame; |
@ -1,13 +1,202 @@ |
|||
import React from "react"; |
|||
import { Text, View } from "react-native"; |
|||
import { useState } from "react"; |
|||
import { Text, TouchableOpacity, View, SafeAreaView } from "react-native"; |
|||
import { useState, useEffect, useRef, useMemo } from "react"; |
|||
import { useDispatch } from "react-redux"; |
|||
import {genSquareChallenge} from '../libs/Random'; |
|||
import {shapes} from '../libs/ShapeEnum'; |
|||
import { styles } from "./styles/AppStyles"; |
|||
import { squareFinished } from "../redux/actions/UserActions"; |
|||
import Autoscroll from "../components/Autoscroll"; |
|||
import Fade from "../components/Fade"; |
|||
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; |
|||
import Icons from '../themes/Icons'; |
|||
import Colors from "../themes/Colors"; |
|||
import Metrics from "../themes/Metrics"; |
|||
|
|||
function Game(props){ |
|||
|
|||
const [squareChallenge, setSquareChallenge] = useState(() => {return genSquareChallenge()}); |
|||
const challengeState = useRef(-1); |
|||
const squareMemo = useMemo(renderPairs, [challengeState.current]); |
|||
const [timerState, setTimerState] = useState(0); |
|||
const localTimer = useRef(null); |
|||
const startTime = useRef(0); |
|||
const answers = useRef(0); |
|||
const [scrollOrigin, setScrollOrigin] = useState(0); |
|||
const scrollDestination = useRef(Metrics.animated.gameScrollInterval); |
|||
const [headerText, setHeaderText] = useState('Ready?'); |
|||
const [headerColor, setHeaderColor] = useState(styles.green); |
|||
const [headerTextColor, setHeaderTextColor] = useState(styles.darkText); |
|||
const dispatch = useDispatch(); |
|||
|
|||
useEffect(() => { |
|||
let headerTimeout = null; |
|||
|
|||
switch(timerState){ |
|||
case 0: |
|||
headerTimeout = setTimeout(() => { |
|||
setHeaderColor(styles.yellow); |
|||
setHeaderText('Set'); |
|||
setTimerState(1); |
|||
}, 1000); |
|||
break; |
|||
case 1: |
|||
headerTimeout = setTimeout(() => { |
|||
setHeaderColor(styles.red); |
|||
setHeaderTextColor(styles.lightText); |
|||
setHeaderText('Go!'); |
|||
challengeState.current = 0; |
|||
setTimerState(2); |
|||
}, 1000); |
|||
break; |
|||
case 2: |
|||
headerTimeout = setTimeout(() => { |
|||
setHeaderColor(styles.dark); |
|||
startTime.current = (Date.now()); |
|||
setHeaderText(0 + ' s'); |
|||
setTimerState(3); |
|||
}, 1000); |
|||
break; |
|||
case 3: |
|||
headerTimeout = setInterval(() => { |
|||
let elapsed = Math.round((Date.now() - startTime.current) / (1000)); |
|||
setHeaderText(elapsed + ' s'); |
|||
}, 1000); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
localTimer.current = headerTimeout; |
|||
|
|||
return () => { |
|||
clearTimeout(localTimer.current); |
|||
clearInterval(localTimer.current); |
|||
} |
|||
}, [timerState]); |
|||
|
|||
|
|||
|
|||
function selectAnswer(pairIndex, correct){ |
|||
if (pairIndex === challengeState.current){ |
|||
if (correct) { |
|||
answers.current = answers.current + 1; |
|||
} |
|||
|
|||
let newOrigin = scrollDestination.current; |
|||
let newDestination = scrollDestination.current - Metrics.animated.gameScrollInterval; |
|||
|
|||
scrollDestination.current = newDestination; |
|||
challengeState.current = challengeState.current + 1; |
|||
setScrollOrigin(newOrigin); |
|||
|
|||
if (challengeState.current >= 20) { |
|||
completeChallenge(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function completeChallenge(){ |
|||
let unformatted = (Date.now() - startTime.current) / (1000); |
|||
let finalTime = Number.parseFloat(unformatted).toFixed(3); |
|||
clearInterval(localTimer.current); |
|||
setHeaderColor(styles.darkGreen); |
|||
setHeaderText(finalTime + ' s'); |
|||
setTimerState(4); |
|||
dispatch(squareFinished(answers.current, finalTime)); |
|||
} |
|||
|
|||
function generateSquare(pairIndex){ |
|||
return ( |
|||
<TouchableOpacity |
|||
onPress={() => selectAnswer(pairIndex, true)} |
|||
style={[styles.darkGreen, styles.answerButton, styles.dropShadow, styles.centeredItems, styles.centeredJustify]} |
|||
> |
|||
<MaterialIcon |
|||
name={Icons.squareIcons.square} |
|||
color={Colors.material.light} |
|||
size={Metrics.icons.buttonIcon} |
|||
/> |
|||
</TouchableOpacity> |
|||
) |
|||
} |
|||
|
|||
function generateShape(index, pairIndex){ |
|||
return ( |
|||
<View> |
|||
<Text style={{color: 'black'}}>test</Text> |
|||
<TouchableOpacity |
|||
onPress={() => selectAnswer(pairIndex, false)} |
|||
style={[styles.darkGreen, styles.answerButton, styles.dropShadow, styles.centeredItems, styles.centeredJustify]} |
|||
> |
|||
<MaterialIcon |
|||
name={shapes[index]} |
|||
color={Colors.material.light} |
|||
size={Metrics.icons.buttonIcon} |
|||
/> |
|||
</TouchableOpacity> |
|||
) |
|||
} |
|||
|
|||
function generatePair(answer, shapeIndex, pairIndex) { |
|||
if (answer === 0) { |
|||
return ( |
|||
<Fade key={pairIndex} faded={challengeState.current !== pairIndex} duration={250}> |
|||
<View style={[styles.flexRow, styles.spaceEvenly, styles.buttonMargin]}> |
|||
{generateSquare(pairIndex)} |
|||
{generateShape(shapeIndex, pairIndex)} |
|||
</View> |
|||
</Fade> |
|||
); |
|||
} else { |
|||
return ( |
|||
<Fade key={pairIndex} faded={challengeState.current !== pairIndex} duration={250}> |
|||
<View style={[styles.flexRow, styles.spaceEvenly, styles.buttonMargin]}> |
|||
{generateShape(shapeIndex, pairIndex)} |
|||
{generateSquare(pairIndex)} |
|||
</View> |
|||
</Fade> |
|||
); |
|||
} |
|||
} |
|||
|
|||
function renderPairs(){ |
|||
return squareChallenge.map((pair, index) => { |
|||
return generatePair(pair.squarePos, pair.shapeType, index); |
|||
}); |
|||
} |
|||
|
|||
return ( |
|||
<SafeAreaView style={styles.flex}> |
|||
<View style={[styles.timerView, headerColor, styles.centeredJustify]}> |
|||
<Text style={[headerTextColor, styles.headerTitleFont, styles.centeredText]}> |
|||
{headerText} |
|||
</Text> |
|||
</View> |
|||
<View style={[styles.flex, styles.flexColumn]}> |
|||
<Autoscroll |
|||
origin={scrollOrigin} |
|||
destination={scrollDestination.current} |
|||
duration={250} |
|||
> |
|||
<View style={[styles.gameView]} /> |
|||
{squareMemo} |
|||
<View style={[styles.gameView, styles.flexRow, styles.spaceEvenly, styles.centeredItems]}> |
|||
<MaterialIcon |
|||
name={Icons.squareIcons.check} |
|||
color={Colors.material.green800} |
|||
size={Metrics.icons.buttonIcon} |
|||
/> |
|||
<Text style={[styles.headerTitleFont, styles.greyText]}> |
|||
Finish |
|||
</Text> |
|||
</View> |
|||
</Autoscroll> |
|||
</View> |
|||
<View style={[styles.timerView, styles.dark, styles.centeredJustify]}> |
|||
<Text style={[styles.lightText, styles.headerTitleFont, styles.centeredText]}> |
|||
{answers.current + ' / ' + squareChallenge.length} |
|||
</Text> |
|||
</View> |
|||
</SafeAreaView> |
|||
); |
|||
} |
|||
|
|||
|
@ -1,14 +1,74 @@ |
|||
import React from "react"; |
|||
import { Text, View } from "react-native"; |
|||
import { useState } from "react"; |
|||
import React, { useEffect, useRef, useState } from "react"; |
|||
import { BackHandler, SafeAreaView, Text, TouchableOpacity, View } from "react-native"; |
|||
import { styles } from './styles/AppStyles'; |
|||
import Slider from "../components/Slider"; |
|||
import { useDispatch } from "react-redux"; |
|||
import {goHome} from '../redux/actions/SystemActions'; |
|||
import DbAPI from "../realm/DbAPI"; |
|||
import { ScrollView } from "react-native-gesture-handler"; |
|||
|
|||
function HighScore(props){ |
|||
function HighScore(){ |
|||
const dispatch = useDispatch(); |
|||
const scores = useRef([]); |
|||
const [scoresLoaded, setScoresLoaded] = useState(false); |
|||
|
|||
useEffect(() => { |
|||
BackHandler.addEventListener('hardwareBackPress', () => {return true}); |
|||
}, []) |
|||
|
|||
useEffect(() => { |
|||
if (!scoresLoaded) { |
|||
loadScores() |
|||
.then(() => { |
|||
setScoresLoaded(true); |
|||
}); |
|||
} |
|||
}, [scoresLoaded]) |
|||
|
|||
function onPressMainMenu(){ |
|||
dispatch(goHome()); |
|||
} |
|||
|
|||
async function loadScores(){ |
|||
scores.current = DbAPI.getHighScores(); |
|||
} |
|||
|
|||
function renderScore(score, index){ |
|||
return ( |
|||
<Text key={index} style={[styles.largeFont, styles.darkText, styles.leftText]}> |
|||
{(index+1) + '. '} |
|||
<Text style={[styles.greyText]}> |
|||
{score.value + ' - ' + score.user} |
|||
</Text> |
|||
</Text> |
|||
) |
|||
} |
|||
|
|||
function renderScores(){ |
|||
return scores.current.map((score, index) => { |
|||
return renderScore(score, index); |
|||
}) |
|||
} |
|||
|
|||
return ( |
|||
<View> |
|||
<Text style={{color: 'black'}}>test</Text> |
|||
<SafeAreaView style={[styles.flex]}> |
|||
<View style={[styles.flex, styles.spaceEvenly]}> |
|||
<Slider origin={400} duration={750} delay={0}> |
|||
<TouchableOpacity |
|||
onPress={onPressMainMenu} |
|||
style={[styles.centeredSelf, styles.centeredJustify, styles.darkGreen, styles.menuButton, styles.dropShadow, styles.smallMargin]} |
|||
> |
|||
<Text style={[styles.lightText, styles.headerTitleFont, styles.boldText, styles.centeredText]}> |
|||
Main Menu |
|||
</Text> |
|||
</TouchableOpacity> |
|||
</Slider> |
|||
<ScrollView style={[styles.flex, styles.smallMargin]}> |
|||
{renderScores()} |
|||
</ScrollView> |
|||
</View> |
|||
); |
|||
</SafeAreaView> |
|||
) |
|||
} |
|||
|
|||
export default HighScore; |
@ -1,14 +1,103 @@ |
|||
import React from "react"; |
|||
import { Text, View } from "react-native"; |
|||
import { useState } from "react"; |
|||
import React, { useEffect, useState } from "react"; |
|||
import { BackHandler, SafeAreaView, Text, TextInput, TouchableOpacity, View } from "react-native"; |
|||
import { styles } from './styles/AppStyles'; |
|||
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons'; |
|||
import Icons from '../themes/Icons'; |
|||
import Colors from "../themes/Colors"; |
|||
import Metrics from "../themes/Metrics"; |
|||
import Slider from "../components/Slider"; |
|||
import { useDispatch, useSelector } from "react-redux"; |
|||
import {squareStartPressed} from '../redux/actions/UserActions'; |
|||
import { goToScores } from "../redux/actions/SystemActions"; |
|||
import ModePicker from '../components/ScrollingPicker'; |
|||
|
|||
function Home(props){ |
|||
function Home(){ |
|||
const dispatch = useDispatch(); |
|||
const [mode, setMode] = useState('square'); |
|||
const userRedux = useSelector((state) => state.user); |
|||
const [username, setUsername] = useState(() => {return userRedux.username}) |
|||
|
|||
useEffect(() => { |
|||
BackHandler.addEventListener('hardwareBackPress', () => {return true}); |
|||
}, []) |
|||
|
|||
function onPressStart(){ |
|||
dispatch(squareStartPressed(mode, username)); |
|||
} |
|||
|
|||
function onPressHighScores(){ |
|||
dispatch(goToScores()); |
|||
} |
|||
|
|||
function setGameMode(newMode) { |
|||
setMode(newMode); |
|||
} |
|||
|
|||
const now = new Date(Date.now()); |
|||
|
|||
return ( |
|||
<View> |
|||
<Text style={{color: 'black'}}>test</Text> |
|||
<SafeAreaView style={[styles.flex]}> |
|||
<View style={[styles.flexHalf, styles.spaceEvenly]}> |
|||
<View style={styles.flex}> |
|||
<Text style={[styles.boldText, styles.headerTitleFont, styles.centeredText, styles.darkText]}> |
|||
Square |
|||
<Text style={[styles.green, styles.headerTitleFont, styles.centeredText, styles.lightText]}> |
|||
{' not '} |
|||
</Text> |
|||
<Text style={[styles.headerTitleFont, styles.centeredText, styles.darkText]}> |
|||
Square |
|||
</Text> |
|||
</Text> |
|||
</View> |
|||
<View style={[styles.flex, styles.centeredSelf]}> |
|||
<ModePicker mode={mode} modeSetter={setGameMode}/> |
|||
<Text style={[styles.largeFont, styles.darkText, styles.centeredText]}> |
|||
{mode === 'square' ? 'Squares' : 'Addition'} |
|||
</Text> |
|||
</View> |
|||
</View> |
|||
<View style={[styles.flex, styles.centeredItems, styles.spaceEvenly]}> |
|||
<Slider origin={400} duration={750} delay={0}> |
|||
<TouchableOpacity |
|||
onPress={onPressStart} |
|||
style={[styles.centeredJustify, styles.darkGreen, styles.menuButton, styles.dropShadow]} |
|||
> |
|||
<Text style={[styles.lightText, styles.headerTitleFont, styles.boldText, styles.centeredText]}> |
|||
Start |
|||
</Text> |
|||
</TouchableOpacity> |
|||
</Slider> |
|||
<Slider origin={400} duration={750} delay={100}> |
|||
<TouchableOpacity |
|||
onPress={onPressHighScores} |
|||
style={[styles.centeredJustify, styles.darkGreen, styles.menuButton, styles.dropShadow]} |
|||
> |
|||
<Text style={[styles.lightText, styles.headerTitleFont, styles.boldText, styles.centeredText]}> |
|||
High Scores |
|||
</Text> |
|||
</TouchableOpacity> |
|||
</Slider> |
|||
</View> |
|||
<View style={[styles.flexRow, styles.centeredJustify, styles.centeredItems]}> |
|||
<MaterialIcon |
|||
name={Icons.squareIcons.edit} |
|||
color={Colors.material.grey400} |
|||
size={Metrics.icons.inputIcon} |
|||
/> |
|||
<TextInput |
|||
style={[styles.darkText, styles.headerTitleFont, styles.usernameInput]} |
|||
placeholder={'username'} |
|||
value={username} |
|||
onChangeText={(updated) => setUsername(updated)} |
|||
/> |
|||
</View> |
|||
<View style={[styles.footer, styles.centeredJustify]}> |
|||
<Text style={[styles.greyText, styles.tinyFont, styles.centeredText]}> |
|||
0.0.1a Atonal Software Aug 10 2022 |
|||
</Text> |
|||
</View> |
|||
); |
|||
</SafeAreaView> |
|||
) |
|||
} |
|||
|
|||
export default Home; |
@ -0,0 +1,113 @@ |
|||
import React, { useEffect, useRef } from "react"; |
|||
import { useSelector } from "react-redux"; |
|||
import { BackHandler, SafeAreaView, Text, TouchableOpacity, View } from "react-native"; |
|||
import { styles } from './styles/AppStyles'; |
|||
import Slider from "../components/Slider"; |
|||
import { useDispatch } from "react-redux"; |
|||
import {goHome, goToScores} from '../redux/actions/SystemActions'; |
|||
|
|||
function Score(props){ |
|||
const dispatch = useDispatch(); |
|||
const userRedux = useSelector((state) => state.user); |
|||
const timerScore = useRef(calculateTimerScore()); |
|||
const answerScore = useRef(calculateAnswerScore()); |
|||
const finalScore = useRef(calculateFinalScore(timerScore.current, answerScore.current)); |
|||
|
|||
|
|||
useEffect(() => { |
|||
BackHandler.addEventListener('hardwareBackPress', () => {return true}); |
|||
}, []) |
|||
|
|||
function calculateTimerScore(user = userRedux){ |
|||
if (user !== null){ |
|||
let score = Math.round((60 - user.lastGameTime) * 1000); |
|||
if (score < 0) { |
|||
return 0; |
|||
} else { |
|||
return score; |
|||
} |
|||
} else { |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
function calculateAnswerScore(user = userRedux) { |
|||
if (user !== null) { |
|||
let score = (user.lastGameAnswers * 1000); |
|||
return score; |
|||
} else { |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
function calculateFinalScore(timerScore, answerScore) { |
|||
let score = timerScore + answerScore; |
|||
return score; |
|||
} |
|||
|
|||
function onPressMainMenu(){ |
|||
dispatch(goHome()); |
|||
} |
|||
|
|||
function onPressHighScores(){ |
|||
dispatch(goToScores()); |
|||
} |
|||
|
|||
const now = new Date(Date.now()); |
|||
|
|||
return ( |
|||
<SafeAreaView style={[styles.flex]}> |
|||
<View style={[styles.flex, styles.spaceEvenly]}> |
|||
<Slider origin={400} duration={750} delay={0}> |
|||
<Text style={[styles.darkText, styles.headerTitleFont, styles.boldText, styles.centeredText]}> |
|||
TIME |
|||
</Text> |
|||
<Text style={[styles.darkText, styles.mediumFont, styles.boldText, styles.centeredText]}> |
|||
{'(60 - ' + userRedux.lastGameTime + ') X 1000 = ' + timerScore.current} |
|||
</Text> |
|||
</Slider> |
|||
<Slider origin={400} duration={750} delay={1000}> |
|||
<Text style={[styles.darkText, styles.headerTitleFont, styles.boldText, styles.centeredText]}> |
|||
ANSWERS |
|||
</Text> |
|||
<Text style={[styles.darkText, styles.mediumFont, styles.boldText, styles.centeredText]}> |
|||
{'('+ userRedux.lastGameAnswers + ') X 1000 = ' + answerScore.current} |
|||
</Text> |
|||
</Slider> |
|||
|
|||
<Slider origin={400} duration={750} delay={2000}> |
|||
<Text style={[styles.darkText, styles.headerTitleFont, styles.boldText, styles.centeredText]}> |
|||
TOTAL |
|||
</Text> |
|||
<Text style={[styles.darkText, styles.mediumFont, styles.boldText, styles.centeredText]}> |
|||
{finalScore.current} |
|||
</Text> |
|||
</Slider> |
|||
</View> |
|||
<View style={[styles.flex, styles.centeredItems, styles.spaceEvenly]}> |
|||
<Slider origin={400} duration={750} delay={3000}> |
|||
<TouchableOpacity |
|||
onPress={onPressMainMenu} |
|||
style={[styles.centeredJustify, styles.darkGreen, styles.menuButton, styles.dropShadow]} |
|||
> |
|||
<Text style={[styles.lightText, styles.headerTitleFont, styles.boldText, styles.centeredText]}> |
|||
Main Menu |
|||
</Text> |
|||
</TouchableOpacity> |
|||
</Slider> |
|||
<Slider origin={400} duration={750} delay={3500}> |
|||
<TouchableOpacity |
|||
onPress={onPressHighScores} |
|||
style={[styles.centeredJustify, styles.darkGreen, styles.menuButton, styles.dropShadow]} |
|||
> |
|||
<Text style={[styles.lightText, styles.headerTitleFont, styles.boldText, styles.centeredText]}> |
|||
High Scores |
|||
</Text> |
|||
</TouchableOpacity> |
|||
</Slider> |
|||
</View> |
|||
</SafeAreaView> |
|||
) |
|||
} |
|||
|
|||
export default Score; |
@ -1,14 +0,0 @@ |
|||
import React from "react"; |
|||
import { Text, View } from "react-native"; |
|||
import { useState } from "react"; |
|||
|
|||
function Settings(props){ |
|||
|
|||
return ( |
|||
<View> |
|||
<Text style={{color: 'black'}}>test</Text> |
|||
</View> |
|||
); |
|||
} |
|||
|
|||
export default Settings; |
@ -1,9 +1,22 @@ |
|||
class AppIcons { |
|||
squareIcons = { |
|||
square: 'square', |
|||
settings: 'cog-outline', |
|||
toggleOn: 'toggle-switch-on', |
|||
toggleOfff: 'toggle-switch-off' |
|||
toggleOff: 'toggle-switch-off', |
|||
check: 'check', |
|||
plus: 'plus', |
|||
edit: 'pencil' |
|||
}; |
|||
|
|||
wrongShapes = { |
|||
rectangle: 'rectangle', |
|||
triangle: 'triangle', |
|||
circle: 'circle', |
|||
hexagon: 'hexagon', |
|||
pentagon: 'pentagon', |
|||
octagon: 'octagon' |
|||
} |
|||
} |
|||
|
|||
const Icons = new AppIcons(); |
|||
|