diff --git a/package-lock.json b/package-lock.json
index 6f1866e..bb038bf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1306,6 +1306,60 @@
"integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==",
"dev": true
},
+ "adbkit": {
+ "version": "2.11.1",
+ "resolved": "https://registry.npmjs.org/adbkit/-/adbkit-2.11.1.tgz",
+ "integrity": "sha512-hDTiRg9NX3HQt7WoDAPCplUpvzr4ZzQa2lq7BdTTJ/iOZ6O7YNAs6UYD8sFAiBEcYHDRIyq3cm9sZP6uZnhvXw==",
+ "requires": {
+ "adbkit-logcat": "^1.1.0",
+ "adbkit-monkey": "~1.0.1",
+ "bluebird": "~2.9.24",
+ "commander": "^2.3.0",
+ "debug": "~2.6.3",
+ "node-forge": "^0.7.1",
+ "split": "~0.3.3"
+ },
+ "dependencies": {
+ "bluebird": {
+ "version": "2.9.34",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.9.34.tgz",
+ "integrity": "sha1-L3tOyAIWMoqf3evfacjUlC/v99g="
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "adbkit-logcat": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/adbkit-logcat/-/adbkit-logcat-1.1.0.tgz",
+ "integrity": "sha1-Adf5sM75CTowvLOwB+//MBUIli8="
+ },
+ "adbkit-monkey": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/adbkit-monkey/-/adbkit-monkey-1.0.1.tgz",
+ "integrity": "sha1-8pG+cBou/FZ6Y/x6pq/N7TFDC+E=",
+ "requires": {
+ "async": "~0.2.9"
+ },
+ "dependencies": {
+ "async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E="
+ }
+ }
+ },
"address": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/address/-/address-1.0.3.tgz",
@@ -3977,8 +4031,7 @@
"commander": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz",
- "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0=",
- "dev": true
+ "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0="
},
"common-tags": {
"version": "1.8.0",
@@ -7066,13 +7119,15 @@
"version": "1.0.0",
"resolved": false,
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": false,
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -7089,19 +7144,22 @@
"version": "1.1.0",
"resolved": false,
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
"resolved": false,
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
"resolved": false,
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -7232,7 +7290,8 @@
"version": "2.0.3",
"resolved": false,
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -7246,6 +7305,7 @@
"resolved": false,
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -7262,6 +7322,7 @@
"resolved": false,
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -7385,7 +7446,8 @@
"version": "1.0.1",
"resolved": false,
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -7536,6 +7598,7 @@
"resolved": false,
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -10192,8 +10255,7 @@
"node-forge": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
- "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==",
- "dev": true
+ "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ=="
},
"node-gyp": {
"version": "3.8.0",
@@ -16733,6 +16795,14 @@
"integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=",
"dev": true
},
+ "split": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
+ "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+ "requires": {
+ "through": "2"
+ }
+ },
"split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
diff --git a/package.json b/package.json
index 02ea827..d3d58a9 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"url": "https://github.com/StarGazer1258/BeatDrop.git"
},
"dependencies": {
+ "adbkit": "^2.11.1",
"adm-zip": "^0.4.13",
"electron-is-dev": "^0.3.0",
"electron-log": "^2.2.17",
diff --git a/src/actions/adbActions.js b/src/actions/adbActions.js
new file mode 100644
index 0000000..7c6325d
--- /dev/null
+++ b/src/actions/adbActions.js
@@ -0,0 +1,295 @@
+import AdmZip from "adm-zip";
+import { ADD_DEVICE, DISPLAY_WARNING, DOWNLOAD_TOOLS, START_ADB_SERVICE, SYNC_DEVICE, UPDATE_DEVICE } from "./types";
+import * as DEVICE from '../constants/devices'
+import * as STATUS from "../constants/device_statuses";
+import os from 'os'
+import path from 'path'
+import fs from 'fs'
+import { exec } from 'child_process'
+import { DEVICE_TYPES } from "../constants/device_types";
+const adb = require('adbkit');
+const Promise = require('bluebird')
+
+export const syncDevice = (serial) => (dispatch, getState) => {
+ let localSongFolder = path.join(getState().settings.installationDirectory, 'Beat Saber_Data', 'CustomLevels')
+ let questSongFolder = ''
+ let command = `-s ${serial} push ${localSongFolder}/. ${questSongFolder} `
+ // execute(command)
+ dispatch({
+ type: SYNC_DEVICE,
+ payload: {
+ deviceId: serial,
+ time: new Date()
+ }
+ })
+}
+
+export const getDevices = () => (dispatch, getState) => {
+ if (!isADBStarted()(getState)){
+ startAdb()(dispatch, getState)
+ dispatch({ type: DISPLAY_WARNING, payload: { text: 'No ADB instance started. Attempting to start...', timeout: 2500 } })
+ return
+ }
+
+ let adb = getState().adb.instance;
+ adb.listDevices().then(devices => {
+ if (devices.length < 1){
+ dispatch({ type: DISPLAY_WARNING, payload:{ text: "No devices found", timeout: 2500 } })
+ return;
+ }
+ devices.forEach(async (device) => {
+ if (device.type === 'device') {
+ if (isDeviceAdded(device)(getState)) return;
+ dispatch({
+ type: ADD_DEVICE,
+ payload: await buildDevice(device.id)(getState)
+ })
+ adb.trackDevices()
+ .then(function(tracker) {
+ console.log('Device %s was plugged in', device.id)
+ tracker.on('add', function(device) {
+ dispatch({
+ type: UPDATE_DEVICE,
+ payload: {
+ deviceId: device.id,
+ status: STATUS.CONNECTED
+ }
+ })
+ })
+ tracker.on('remove', function(device) {
+ console.log('Device %s was unplugged', device.id)
+ dispatch({
+ type: UPDATE_DEVICE,
+ payload: {
+ deviceId: device.id,
+ status: STATUS.OFFLINE
+ }
+ })
+ })
+ tracker.on('end', function() {
+ console.log('Tracking stopped')
+ dispatch({
+ type: UPDATE_DEVICE,
+ payload: {
+ deviceId: device.id,
+ status: STATUS.UNKNOWN
+ }
+ })
+ })
+ })
+ .catch(function(err) {
+ console.error('Something went wrong:', err.stack)
+ })
+ }
+ })
+ })
+}
+
+const downloadADBTools = () => (dispatch, getState) => {
+ let url = 'https://dl.google.com/android/repository/platform-tools-latest-'
+ let name = "windows.zip"
+ switch (os.platform()) {
+ case "win32":
+ name = "windows.zip"
+ break
+ case "darwin":
+ name = "darwin.zip"
+ break
+ case "linux":
+ name = "linux.zip"
+ break
+ default:
+ name = "windows.zip"
+ break;
+ }
+ let downloadLink = url + name
+ let downloadPath = path.join(getState().settings.installationDirectory)
+ let toolsPath = path.join(downloadPath, 'platform-tools');
+ if (fs.existsSync(toolsPath)){
+ dispatch({
+ type: DOWNLOAD_TOOLS,
+ payload: { path: toolsPath, toolsDownloaded: true }
+ })
+ return
+ }
+ return new Promise(async (resolve, reject) => {
+ await fetch(downloadLink)
+ .then(res => res.arrayBuffer())
+ .then((data) => {
+ let zip = new AdmZip(new Buffer(data))
+ try{
+ zip.extractAllTo(downloadPath, true)
+ dispatch({
+ type: DOWNLOAD_TOOLS,
+ payload: { path: toolsPath, toolsDownloaded: true }
+ })
+ } catch (err) {
+ dispatch({
+ type: DISPLAY_WARNING,
+ payload: {
+ text: `Error download ADB tools. Please try again`
+ }
+ })
+ }
+ return resolve(downloadPath)
+ })
+ });
+}
+
+function getAdbBinary() {
+ switch (os.platform()) {
+ case 'darwin':
+ case 'linux':
+ return 'adb';
+ default:
+ return 'adb.exe';
+ }
+}
+
+const execute = (command) => (getState) => {
+ return new Promise(async (resolve, reject) => {
+ let adbP = path.join(getState().adb.toolsPath, getAdbBinary())
+ await exec('"' + adbP + '" ' + command, (err, stdout, stderr) => {
+ if (err || stderr) return reject(err || stderr)
+ return resolve(stdout)
+ })
+ })
+}
+
+const getProperty = (serial, property) => (getState) => {
+ return new Promise(async (resolve, reject) => {
+ let command = `-s ${serial} shell getprop ${property}`
+ return await execute(command)(getState)
+ .catch((error) => {
+ return reject(error)
+ })
+ .then((result) => {
+ return resolve(result)
+ })
+ })
+}
+
+const getStorage = (serial) => (getState) => {
+ return new Promise(async (resolve, reject) => {
+ let command = `-s ${serial} shell df`
+ return await execute(command)(getState)
+ .catch((error) => {
+ return reject(error)
+ })
+ .then((result) => {
+ return resolve(result)
+ })
+ })
+}
+
+const listDevices = () => (getState) => {
+ let command = `devices`
+ execute(command)(getState).then((result) => {
+ console.log(result)
+ })
+}
+
+const buildDevice = (serial) => (getState) => {
+ return new Promise(async (resolve, reject) => {
+ let info = {
+ used: 0,
+ avail: 0
+ };
+ await getProperty(serial, 'ro.product.manufacturer')(getState)
+ .catch((error) => {
+ console.log(error)
+ })
+ .then((manufacturer) => {
+ info.manufacturer = manufacturer.toString().replace("\n", '')
+ })
+ .catch((error) => {
+ console.log(error)
+ })
+ .then(() => {
+ return getProperty(serial, 'ro.product.model')(getState)
+ })
+ .catch((error) => {
+ console.log(error)
+ })
+ .then((model) => {
+ info.model = model.toString().replace("\n", '')
+ })
+ .catch((error) => {
+ console.log(error)
+ })
+ .then(() => {
+ info.device = `${info.manufacturer} ${info.model}`
+ })
+
+ await getStorage(serial)(getState).then(async (storage) => {
+ let storageArr = parseStorage(storage)
+ storageArr.forEach((filesystem) => {
+ if (isNaN(filesystem.used) || isNaN(filesystem.avail)) return
+ let used = Number(filesystem.used)
+ let avail = Number(filesystem.avail)
+ info.used += Math.round(( used / 1000))
+ info.avail += Math.round((avail / 1000))
+ })
+ })
+
+ if (info.manufacturer.includes(DEVICE_TYPES.MANUFACTURER.OCULUS)) {
+ if( info.model.includes(DEVICE_TYPES.MODEL.QUEST)){
+ return resolve([{
+ type: DEVICE.OCULUS.QUEST,
+ status: STATUS.CONNECTED,
+ storageUsed: info.used,
+ capacity: info.avail + info.used,
+ deviceId: serial,
+ lastSync: 'N/A'
+ }])
+ }
+ }
+ })
+}
+
+const parseStorage = (str) => {
+ let strArr = str.split('\n')
+ let newArr = [];
+ strArr.forEach((item)=>{
+ newArr.push([item.split(' ').filter((e)=>{return e})])
+ })
+ let arrObj = []
+ newArr.forEach((innerArr)=>{
+ innerArr.forEach((nextArr)=>{
+ if (nextArr[3] === undefined) return
+ arrObj.push({
+ filesystem: nextArr[0],
+ kblocks: nextArr[1],
+ used: nextArr[2],
+ avail: nextArr[3],
+ usePer: nextArr[4],
+ mountLoc: nextArr[5],
+ })
+ })
+ })
+ return arrObj
+}
+
+const startAdb = () => async (dispatch, getState) => {
+ if (!areToolsDownloaded()(getState)) await downloadADBTools()(dispatch, getState)
+ if (getState().adb.instance && getState().adb.instance.constructor.name === "Client") return
+ dispatch({
+ type: START_ADB_SERVICE,
+ payload: { instance: adb.createClient({ bin: path.join(getState().adb.toolsPath, getAdbBinary()) }), started: true }
+ })
+ getDevices()(dispatch, getState)
+}
+
+const isADBStarted = () => (getState) => {
+ return !!getState().adb.instance && getState().adb.toolsDownloaded && fs.existsSync(getState().adb.toolsPath) && getState().adb.instance.constructor.name === "Client"
+}
+
+const areToolsDownloaded = () => (getState) => {
+ return getState().adb.toolsDownloaded && getState().adb.toolsPath && fs.existsSync(getState().adb.toolsPath)
+}
+
+const isDeviceAdded = (device) => getState => {
+ let found = false;
+ getState().devices.list.some((someDevice) => { if (someDevice.deviceId === device.id) found = true })
+ return found
+}
\ No newline at end of file
diff --git a/src/actions/types.js b/src/actions/types.js
index 2d073a5..e0330fa 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -102,4 +102,15 @@ export const SET_DOWNLOADED_SONGS = 'SET_DOWNLOADED_SONGS'
// Devices
export const SCAN_DEVICES = 'SCAN_DEVICES'
-export const SELECT_DEVICE = 'SELECT_DEVICE'
\ No newline at end of file
+export const SELECT_DEVICE = 'SELECT_DEVICE'
+export const ADD_DEVICE = 'ADD_DEVICE'
+export const UPDATE_DEVICE = 'UPDATE_DEVICE'
+export const SYNC_DEVICE = 'SYNC_DEVICE'
+
+// ADB
+export const DOWNLOAD_TOOLS = 'DOWNLOAD_TOOLS'
+export const START_ADB_SERVICE = 'START_ADB_SERVICE'
+export const STOP_ADB_SERVICE = 'STOP_ADB_SERVICE'
+export const PULL = 'PULL'
+export const PUSH = 'PUSH'
+export const INSTALL = 'INSTALL'
\ No newline at end of file
diff --git a/src/assets/sync-f.png b/src/assets/sync-f.png
new file mode 100644
index 0000000..f5cfee3
Binary files /dev/null and b/src/assets/sync-f.png differ
diff --git a/src/components/App.js b/src/components/App.js
index 21c4592..82f1189 100644
--- a/src/components/App.js
+++ b/src/components/App.js
@@ -11,7 +11,6 @@ import UpdateDialog from './UpdateDialog';
import SongScanningDialog from './SongScanningDialog';
import ReleaseNotesModal from './ReleaseNotesModal'
import CrashMessage from './CrashMessage'
-
import { connect } from 'react-redux'
import { setHasError } from '../actions/windowActions'
@@ -19,8 +18,8 @@ import { downloadSong } from '../actions/queueActions'
import { loadModDetails, installMod } from '../actions/modActions'
import { loadDetailsFromKey } from '../actions/detailsActions'
import { setView } from '../actions/viewActions'
-import { fetchLocalPlaylists } from '../actions/playlistsActions'
+import { fetchLocalPlaylists } from '../actions/playlistsActions'
import { SONG_DETAILS, SONG_LIST, MOD_DETAILS, MODS_VIEW } from '../views'
const { ipcRenderer } = window.require('electron')
@@ -41,7 +40,6 @@ class App extends Component {
setView(SONG_LIST)(store.dispatch, store.getState)
}
loadDetailsFromKey()(store.dispatch, store.getState)
-
}
for(let i = 0; i < message.mods.details.length; i++) {
if(store.getState().view.view === MOD_DETAILS && store.getState().view.previousView !== MOD_DETAILS) {
diff --git a/src/components/DeviceDetails.js b/src/components/DeviceDetails.js
index 0d2c2ed..dbea1f7 100644
--- a/src/components/DeviceDetails.js
+++ b/src/components/DeviceDetails.js
@@ -4,7 +4,8 @@ import '../css/DeviceDetails.scss'
import ProgressBar from './ProgressBar'
import deleteIcon from '../assets/delete-filled.png'
-import addIcon from '../assets/add-filled.png'
+import syncIcon from '../assets/sync-f.png'
+import { syncDevice } from '../actions/adbActions'
//import moreIcon from '../assets/more-filled.png'
import { connect } from 'react-redux'
@@ -28,9 +29,10 @@ class DeviceDetails extends Component {
{ `${this.props.device.type.vendorName} ${this.props.device.type.deviceName}` }
{ this.props.device.status }
- { this.props.device.type.identifier === DEVICE.OCULUS.QUEST.identifier ?
{} }>ADD SONGS : null }
+ { this.props.device.type.identifier === DEVICE.OCULUS.QUEST.identifier ?
{ this.props.syncDevice(this.props.device.deviceId) } }>SYNC SONGS : null }
{} }>REMOVE DEVICE
+ Last sync: { this.props.device.lastSync }
Storage
{ this.props.device.capacity ? : null }
{ this.props.device.capacity ? `${Math.trunc(this.props.device.storageUsed / this.props.device.capacity * 100)}% (${this.props.device.storageUsed / 1000}GB / ${this.props.device.capacity / 1000}GB)` : 'N/A' }
@@ -44,8 +46,9 @@ class DeviceDetails extends Component {
}
const mapStateToProps = state => ({
+ deviceId: state.devices.selectedDevice,
device: state.devices.list[state.devices.selectedDevice],
previousView: state.view.previousView
})
-export default connect(mapStateToProps, { setView })(DeviceDetails)
\ No newline at end of file
+export default connect(mapStateToProps, { setView, syncDevice })(DeviceDetails)
\ No newline at end of file
diff --git a/src/components/DevicesView.js b/src/components/DevicesView.js
index ff8aa55..5076d8b 100644
--- a/src/components/DevicesView.js
+++ b/src/components/DevicesView.js
@@ -4,48 +4,40 @@ import '../css/DevicesView.scss'
import { connect } from 'react-redux'
import { selectDevice } from '../actions/deviceActions'
+import { getDevices } from "../actions/adbActions";
import { setView } from '../actions/viewActions'
import { DEVICE_DETAILS } from '../views'
-import * as DEVICE from '../constants/devices'
-import * as STATUS from '../constants/device_statuses'
-
const { remote } = window.require('electron')
const path = remote.require('path')
-let devices = [
- {
- type: DEVICE.OCULUS.QUEST,
- status: STATUS.CONNECTED,
- storageUsed: 15400,
- capacity: 32000
- },
- {
- type: DEVICE.HTC.VIVE,
- status: STATUS.CONNECTED,
- },
- {
- type: DEVICE.HTC.VIVE_PRO,
- status: STATUS.OFFLINE
- },
- {
- type: DEVICE.OCULUS.RIFT,
- status: STATUS.OFFLINE
- },
- {
- type: DEVICE.OCULUS.RIFT_S,
- status: STATUS.OFFLINE
- },
- {
- type: DEVICE.PIMAX.EIGHT_K,
- status: STATUS.OFFLINE
- }
-]
-
class DevicesView extends Component {
+ componentWillMount(){
+ this.props.getDevices()
+ }
+
render() {
+ if (!this.props.devices || this.props.devices.length === 0) {
return (
+
+
Devices
+
+
+ | Device Name | Status | Storage |
+
+
+ {
+
+ No devices found. Click to scan for more.
+
+ }
+
+
+
+ )
+ } else {
+ return (
Devices
@@ -54,7 +46,7 @@ class DevicesView extends Component {
{
- devices.map((device, i) => {
+ this.props.devices.map((device, i) => {
return (
{ this.props.selectDevice(i); this.props.setView(DEVICE_DETAILS) } }>
|
@@ -69,11 +61,13 @@ class DevicesView extends Component {
)
+ }
}
}
const mapStateToProps = state => ({
-
+ devices: state.devices.list,
+ adb: state.adb
})
-export default connect(mapStateToProps, { selectDevice, setView })(DevicesView)
\ No newline at end of file
+export default connect(mapStateToProps, { selectDevice, setView, getDevices })(DevicesView)
\ No newline at end of file
diff --git a/src/constants/device_types.js b/src/constants/device_types.js
new file mode 100644
index 0000000..bc6675f
--- /dev/null
+++ b/src/constants/device_types.js
@@ -0,0 +1,13 @@
+export const DEVICE_TYPES = {
+ MANUFACTURER: {
+ OCULUS: 'Oculus',
+ HTC: "HTC"
+ },
+ MODEL: {
+ QUEST: 'Quest',
+ RIFT: 'Rift',
+ RIFT_S: 'Rift S',
+ GO: 'Go',
+ VIVE: 'Vive'
+ }
+}
\ No newline at end of file
diff --git a/src/constants/devices.js b/src/constants/devices.js
index c1901b6..e03ffc6 100644
--- a/src/constants/devices.js
+++ b/src/constants/devices.js
@@ -12,16 +12,14 @@ export const OCULUS = {
vendorName: 'Oculus',
deviceName: 'Rift S',
identifier: 'OCULUS_RIFT_S',
- vendorId: 0x2833,
- deviceId: null
+ vendorId: 0x2833
},
QUEST: {
image: 'src/assets/quest.png',
vendorName: 'Oculus',
deviceName: 'Quest',
identifier: 'OCULUS_QUEST',
- vendorId: 0x2833,
- deviceId: null
+ vendorId: 0x2833
}
}
@@ -31,16 +29,14 @@ export const HTC = {
vendorName: 'HTC',
deviceName: 'Vive',
identifier: 'HTC_VIVE',
- vendorId: null,
- deviceId: null
+ vendorId: null
},
VIVE_PRO: {
image: 'src/assets/vive-pro.png',
vendorName: 'HTC',
deviceName: 'Vive Pro',
identifier: 'HTC_VIVE_PRO',
- vendorId: null,
- deviceId: null
+ vendorId: null
}
}
@@ -50,8 +46,7 @@ export const VALVE = {
vendorName: 'Valve',
deviceName: 'Index',
identifier: 'INDEX',
- vendorId: 0x28de,
- deviceId: null
+ vendorId: 0x28de
}
}
@@ -61,7 +56,6 @@ export const PIMAX = {
vendorName: 'Pimax',
deviceName: '8K',
identifier: 'PIMAX_EIGHT_K',
- vendorId: null,
- deviceId: null
+ vendorId: null
}
}
\ No newline at end of file
diff --git a/src/reducers/adbReducer.js b/src/reducers/adbReducer.js
new file mode 100644
index 0000000..58b4867
--- /dev/null
+++ b/src/reducers/adbReducer.js
@@ -0,0 +1,27 @@
+import { START_ADB_SERVICE, DOWNLOAD_TOOLS } from "../actions/types";
+
+const initialState = {
+ instance: null,
+ started: false,
+ toolsDownloaded: false,
+ toolsPath: ''
+}
+
+export default (state = initialState, action) => {
+ switch (action.type) {
+ case START_ADB_SERVICE:
+ return {
+ ...state,
+ instance: action.payload.instance,
+ started: action.payload.started
+ }
+ case DOWNLOAD_TOOLS:
+ return {
+ ...state,
+ toolsPath: action.payload.path,
+ toolsDownloaded: action.payload.toolsDownloaded
+ }
+ default:
+ return state
+ }
+}
diff --git a/src/reducers/deviceReducer.js b/src/reducers/deviceReducer.js
index 7eb53ff..96d2e0a 100644
--- a/src/reducers/deviceReducer.js
+++ b/src/reducers/deviceReducer.js
@@ -1,37 +1,7 @@
-import { SELECT_DEVICE } from '../actions/types'
-
-import * as DEVICE from '../constants/devices'
-import * as STATUS from '../constants/device_statuses'
+import { ADD_DEVICE, SELECT_DEVICE, SYNC_DEVICE, UPDATE_DEVICE } from "../actions/types";
const initialState = {
- list: [
- {
- type: DEVICE.OCULUS.QUEST,
- status: STATUS.CONNECTED,
- storageUsed: 15400,
- capacity: 32000
- },
- {
- type: DEVICE.HTC.VIVE,
- status: STATUS.CONNECTED,
- },
- {
- type: DEVICE.HTC.VIVE_PRO,
- status: STATUS.OFFLINE
- },
- {
- type: DEVICE.OCULUS.RIFT,
- status: STATUS.OFFLINE
- },
- {
- type: DEVICE.OCULUS.RIFT_S,
- status: STATUS.OFFLINE
- },
- {
- type: DEVICE.PIMAX.EIGHT_K,
- status: STATUS.OFFLINE
- }
- ],
+ list: [],
selectedDevice: 0
}
@@ -42,6 +12,27 @@ export default function(state = initialState, action) {
...state,
selectedDevice: action.payload
}
+ case ADD_DEVICE:
+ return {
+ ...state,
+ list: [...state.list, ...action.payload]
+ }
+ case UPDATE_DEVICE:
+ let deviceId = action.payload.deviceId;
+ let status = action.payload.status;
+ return {
+ ...state,
+ list: state.list.map(device => device.deviceId === deviceId ? { ...device, status: status } : device)
+ }
+ case SYNC_DEVICE:
+ let time = action.payload.time;
+ let date = `${time.getFullYear()}-${time.getMonth() + 1}-${time.getDate()}`
+ let timeInHours = `${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}`
+ let dateTime = `${date} ${timeInHours}`
+ return {
+ ...state,
+ list: state.list.map(device => device.deviceId === action.payload.deviceId ? { ...device, lastSync: dateTime } : device)
+ }
default:
return state
}
diff --git a/src/reducers/index.js b/src/reducers/index.js
index 698bf00..07fe38c 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -14,6 +14,7 @@ import playlistsReducer from './playlistsReducer'
import searchReducer from './searchReducer'
import modReducer from './modReducer'
import deviceReducer from './deviceReducer'
+import adbReducer from "./adbReducer";
export default combineReducers({
songs: songListReducer,
@@ -30,5 +31,6 @@ export default combineReducers({
queue: queueReducer,
warnings: warningsReducer,
search: searchReducer,
- devices: deviceReducer
+ devices: deviceReducer,
+ adb: adbReducer,
})
\ No newline at end of file