import Tab from '../../components/Tabs/tabType'
import connector from '../../../main/connector'
import { convertToJS, getFile, create, lengthBetween } from '../../../main/pieceTable'
/**
* Manages the changes of files on the server, and manages the list of tabs.
*
* @module fileTracker
*/
const state = {
pieces: null,
pieceTable: null,
openFile: '',
filePaths: '',
tabs: []
}
const mutations = {
serverURLChange (store) {
},
/**
* Updates the pieces using the getFile function from pieceTable.js
* @param {Object} state
* @param {pieceTable} pieceTable
*/
updatePieces (state, pieceTable) {
state.pieces = getFile(pieceTable)
},
/**
* Removes all tabs.
* @param {Object} state
*/
clearTabs (state) {
state.tabs = []
},
/**
* Updates the pieceTable.
* @param {Object} state
* @param {pieceTable} pieceTable
*/
updatePieceTable (state, pieceTable) {
state.pieceTable = pieceTable
},
/**
* Adds a tab to state.
* @param {Object} state vuex state
* @param {string} filePath filepath to file that needs to be added as tab
*/
addTab (state, filePath) {
if (state.tabs.every(x => x.filePath !== filePath)) {
const newTab = new Tab(filePath)
state.tabs = [...state.tabs, newTab]
}
},
/**
* Removes tab from state.
* @param {Object} state vuex state
* @param {string} filePath filepath to file of the tab that needs to removed
*/
removeTab (state, tabPath) {
state.tabs = state.tabs.filter(x => x.filePath !== tabPath)
},
/**
* Updates the filepaths.
* @param {Object} state vuex state
* @param {Object[]} filePaths
*/
updateFiles (state, filePaths) {
state.filePaths = filePaths
},
updateOpenFile (state, filePath) {
state.openFile = filePath
},
/**
* Renames a given tab.
* @param {Object} store vuex store
* @param {Object} payload a key array with keys pathToDir, the path to the
* directory in which the file is located (has to end on '/'), oldName, the
* current name of the file, and newName, the new name of the file.
* They are stored in one object because this can't be done differently for mutations.
*/
renameTab (state, payload) {
if (payload.pathToDir + payload.oldName === state.openFile) {
state.openFile = payload.pathToDir + payload.newName
}
for (let tab of state.tabs) {
if (tab.fileName === payload.oldName) {
tab.filePath = payload.pathToDir + payload.newName
tab.fileName = payload.newName
break
}
}
}
}
const actions = {
/**
* Opens a file from the root of the project, and updates the code.
* Also changes the openedFile state. Add the file to the tabs.
* @param {Object} store vuex store
* @param {string} filePath the file path to document to be opened
*/
openFile (store, filePath) {
if (filePath === store.state.openFile) {
return
}
store.commit('updateOpenFile', filePath)
store.commit('addTab', filePath)
connector.send(
'file-join',
{
'file_path': filePath
}
)
connector.request(
'file-content-request',
'file-content-response',
{
'file_path': filePath,
'start': 0,
'length': -1
}
).then((data) => {
const pieceTable = convertToJS(data)
store.dispatch('updatePieceTable', pieceTable)
})
},
/**
* Move to the tab left from the tab with the given index.
*/
prevTab (store, index) {
if (index === 0) {
index = store.state.tabs.length
}
store.dispatch('openFile', store.state.tabs[index - 1].filePath)
},
/**
* Move to the tab right from the tab with the given index.
*/
nextTab (store, index) {
if (index === store.state.tabs.length - 1) {
index = -1
}
store.dispatch('openFile', store.state.tabs[index + 1].filePath)
},
/**
* Updates pieces and piece table
* @param {Object} store
* @param {PieceTable} pieceTable
*/
updatePieceTable (store, pieceTable) {
store.commit('updatePieceTable', pieceTable)
store.commit('updatePieces', pieceTable)
},
serverURLChange (store) {
store.commit('serverURLChange')
store.dispatch('clearTabs')
},
/**
* Removes a tab from state and switches to a new tab if the tab was the
* currently opened tab. The changes made to the tab are also saved, and
* after closing the user is removed from the list of users in a tab.
* @param {Object} store vuex store
* @param {Tab} tabToRemove the tab that needs to be removed
*/
removeTab (store, tabToRemove) {
connector.send('file-leave', {
file_path: store.state.openFile,
force_exit: 1
})
if (tabToRemove.filePath === store.state.openFile) {
if (store.state.tabs.length === 1) {
store.commit('updateOpenFile', '')
store.dispatch('updatePieceTable', create(''))
} else {
const i = store.state.tabs.indexOf(tabToRemove)
store.dispatch('prevTab', i)
}
}
store.commit('removeTab', tabToRemove.filePath)
},
/**
* Removes a tab from state and switches to a new tab if the tab was opened.
* This function only needs the file to be removed, and doesn't save changes or
* update the user list like removeTab does.
* @param {Object} store vuex store
* @param {string} tabPath the path to the tab that needs to be removed
*/
removeTabByPath (store, tabPath) {
if (tabPath === store.state.openFile) {
if (store.state.tabs.length === 1) {
store.commit('updateOpenFile', '')
store.dispatch('updatePieceTable', create(''))
} else {
let i = 0
for (let tab of store.state.tabs) {
if (tab.filePath === tabPath) {
break
}
i++
}
store.dispatch('prevTab', i)
}
}
store.commit('removeTab', tabPath)
},
updateCodeAction (state, newCode) {
state.commit('updateCode', newCode)
},
/**
* Sends a request for a lock to the server.
* @param {Object} state
* @param {{start: {id, offset}, end: {id, offset}}} payload
*/
requestLockAction (state, payload) {
connector.request('file-lock-request', 'file-lock-response',
{
'file_path': state.openFile,
'piece_uuid': payload.start.id,
'offset': payload.start.offset,
'length': lengthBetween(this.state.pieces, payload.start.id,
payload.start.offset, payload.end.start, payload.end.offset)
}
)
},
/**
* Closes all open tabs.
* @param {Object} store
*/
clearTabs (store) {
store.commit('updateOpenFile', '')
store.commit('clearTabs')
store.dispatch('updatePieceTable', create(''))
},
/**
* Moves from the current tab to another tab in the given direction.
* @param {Object} store vuex store
* @param {int} direction 1 for moving to the next tab, 0 for to the previous
*/
scrollTab (store, direction) {
let i = 0
for (let tab of store.state.tabs) {
if (tab.filePath === store.state.openFile) {
if (direction) {
store.dispatch('nextTab', i)
} else {
store.dispatch('prevTab', i)
}
break
}
i++
}
}
}
export default {
state,
mutations,
actions
}