Merge pull request #4942 from overleaf/ae-synctex-controller

Move PdfSynctexController and synctex factory to a separate module

GitOrigin-RevId: 0fdd87425159bbdec21ab5c82c9f4abb47f82d07
This commit is contained in:
Alf Eaton 2021-09-03 10:07:17 +01:00 committed by Copybot
parent deafe456b4
commit 7ba6776b2e
3 changed files with 181 additions and 181 deletions

View file

@ -9,6 +9,7 @@
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
import './controllers/PdfController'
import './controllers/PdfSynctexController'
import './controllers/PdfViewToggleController'
import '../pdfng/directives/pdfJs'

View file

@ -974,187 +974,6 @@ App.controller(
}
)
App.factory('synctex', function (ide, $http, $q) {
const synctex = {
syncToPdfInFlight: false,
syncToCodeInFlight: false,
syncToPdf(cursorPosition) {
const deferred = $q.defer()
const docId = ide.editorManager.getCurrentDocId()
if (docId == null) {
deferred.reject()
return deferred.promise
}
const doc = ide.fileTreeManager.findEntityById(docId)
if (doc == null) {
deferred.reject()
return deferred.promise
}
let path = ide.fileTreeManager.getEntityPath(doc)
if (path == null) {
deferred.reject()
return deferred.promise
}
// If the root file is folder/main.tex, then synctex sees the
// path as folder/./main.tex
const rootDocDirname = ide.fileTreeManager.getRootDocDirname()
if (rootDocDirname != null && rootDocDirname !== '') {
path = path.replace(RegExp(`^${rootDocDirname}`), `${rootDocDirname}/.`)
}
const { row, column } = cursorPosition
this.syncToPdfInFlight = true
$http({
url: `/project/${ide.project_id}/sync/code`,
method: 'GET',
params: {
file: path,
line: row + 1,
column,
clsiserverid: ide.clsiServerId,
},
})
.then(response => {
this.syncToPdfInFlight = false
const { data } = response
return deferred.resolve(data.pdf || [])
})
.catch(response => {
this.syncToPdfInFlight = false
const error = response.data
return deferred.reject(error)
})
return deferred.promise
},
syncToCode(position, options) {
if (options == null) {
options = {}
}
const deferred = $q.defer()
if (position == null) {
deferred.reject()
return deferred.promise
}
// FIXME: this actually works better if it's halfway across the
// page (or the visible part of the page). Synctex doesn't
// always find the right place in the file when the point is at
// the edge of the page, it sometimes returns the start of the
// next paragraph instead.
const h = position.offset.left
// Compute the vertical position to pass to synctex, which
// works with coordinates increasing from the top of the page
// down. This matches the browser's DOM coordinate of the
// click point, but the pdf position is measured from the
// bottom of the page so we need to invert it.
let v
if (
options.fromPdfPosition &&
(position.pageSize != null ? position.pageSize.height : undefined) !=
null
) {
v = position.pageSize.height - position.offset.top || 0 // measure from pdf point (inverted)
} else {
v = position.offset.top || 0 // measure from html click position
}
// It's not clear exactly where we should sync to if it wasn't directly
// clicked on, but a little bit down from the very top seems best.
if (options.includeVisualOffset) {
v += 72 // use the same value as in pdfViewer highlighting visual offset
}
this.syncToCodeInFlight = true
$http({
url: `/project/${ide.project_id}/sync/pdf`,
method: 'GET',
params: {
page: position.page + 1,
h: h.toFixed(2),
v: v.toFixed(2),
clsiserverid: ide.clsiServerId,
},
})
.then(response => {
this.syncToCodeInFlight = false
const { data } = response
if (
data.code != null &&
data.code.length > 0 &&
data.code[0].file !== ''
) {
const doc = ide.fileTreeManager.findEntityByPath(data.code[0].file)
if (doc == null) {
deferred.reject()
}
return deferred.resolve({ doc, line: data.code[0].line })
} else if (data.code[0].file === '') {
ide.$scope.sync_tex_error = true
setTimeout(() => (ide.$scope.sync_tex_error = false), 4000)
}
})
.catch(response => {
this.syncToCodeInFlight = false
const error = response.data
return deferred.reject(error)
})
return deferred.promise
},
}
return synctex
})
App.controller('PdfSynctexController', function ($scope, synctex, ide) {
this.cursorPosition = null
$scope.$watch(
() => synctex.syncToPdfInFlight,
value => ($scope.syncToPdfInFlight = value)
)
$scope.$watch(
() => synctex.syncToCodeInFlight,
value => ($scope.syncToCodeInFlight = value)
)
ide.$scope.$on('cursor:editor:update', (event, cursorPosition) => {
this.cursorPosition = cursorPosition
})
$scope.syncToPdf = () => {
if (this.cursorPosition == null) {
return
}
synctex.syncToPdf(this.cursorPosition).then(highlights => {
$scope.pdf.highlights = highlights
})
}
ide.$scope.$on('cursor:editor:syncToPdf', $scope.syncToPdf)
$scope.syncToCode = function () {
synctex
.syncToCode($scope.pdf.position, {
includeVisualOffset: true,
fromPdfPosition: true,
})
.then(function (data) {
const { doc, line } = data
ide.editorManager.openDoc(doc, { gotoLine: line })
})
}
})
App.controller('ClearCacheModalController', function ($scope, $modalInstance) {
$scope.state = { error: false, inflight: false }

View file

@ -0,0 +1,180 @@
import App from '../../../base'
App.controller('PdfSynctexController', function ($scope, synctex, ide) {
this.cursorPosition = null
$scope.$watch(
() => synctex.syncToPdfInFlight,
value => ($scope.syncToPdfInFlight = value)
)
$scope.$watch(
() => synctex.syncToCodeInFlight,
value => ($scope.syncToCodeInFlight = value)
)
ide.$scope.$on('cursor:editor:update', (event, cursorPosition) => {
this.cursorPosition = cursorPosition
})
$scope.syncToPdf = () => {
if (this.cursorPosition == null) {
return
}
synctex.syncToPdf(this.cursorPosition).then(highlights => {
$scope.pdf.highlights = highlights
})
}
ide.$scope.$on('cursor:editor:syncToPdf', $scope.syncToPdf)
$scope.syncToCode = function () {
synctex
.syncToCode($scope.pdf.position, {
includeVisualOffset: true,
fromPdfPosition: true,
})
.then(function (data) {
const { doc, line } = data
ide.editorManager.openDoc(doc, { gotoLine: line })
})
}
})
App.factory('synctex', function (ide, $http, $q) {
return {
syncToPdfInFlight: false,
syncToCodeInFlight: false,
syncToPdf(cursorPosition) {
const deferred = $q.defer()
const docId = ide.editorManager.getCurrentDocId()
if (docId == null) {
deferred.reject()
return deferred.promise
}
const doc = ide.fileTreeManager.findEntityById(docId)
if (doc == null) {
deferred.reject()
return deferred.promise
}
let path = ide.fileTreeManager.getEntityPath(doc)
if (path == null) {
deferred.reject()
return deferred.promise
}
// If the root file is folder/main.tex, then synctex sees the
// path as folder/./main.tex
const rootDocDirname = ide.fileTreeManager.getRootDocDirname()
if (rootDocDirname != null && rootDocDirname !== '') {
path = path.replace(RegExp(`^${rootDocDirname}`), `${rootDocDirname}/.`)
}
const { row, column } = cursorPosition
this.syncToPdfInFlight = true
$http({
url: `/project/${ide.project_id}/sync/code`,
method: 'GET',
params: {
file: path,
line: row + 1,
column,
clsiserverid: ide.clsiServerId,
},
})
.then(response => {
this.syncToPdfInFlight = false
const { data } = response
return deferred.resolve(data.pdf || [])
})
.catch(response => {
this.syncToPdfInFlight = false
const error = response.data
return deferred.reject(error)
})
return deferred.promise
},
syncToCode(position, options) {
if (options == null) {
options = {}
}
const deferred = $q.defer()
if (position == null) {
deferred.reject()
return deferred.promise
}
// FIXME: this actually works better if it's halfway across the
// page (or the visible part of the page). Synctex doesn't
// always find the right place in the file when the point is at
// the edge of the page, it sometimes returns the start of the
// next paragraph instead.
const h = position.offset.left
// Compute the vertical position to pass to synctex, which
// works with coordinates increasing from the top of the page
// down. This matches the browser's DOM coordinate of the
// click point, but the pdf position is measured from the
// bottom of the page so we need to invert it.
let v
if (
options.fromPdfPosition &&
(position.pageSize != null ? position.pageSize.height : undefined) !=
null
) {
v = position.pageSize.height - position.offset.top || 0 // measure from pdf point (inverted)
} else {
v = position.offset.top || 0 // measure from html click position
}
// It's not clear exactly where we should sync to if it wasn't directly
// clicked on, but a little bit down from the very top seems best.
if (options.includeVisualOffset) {
v += 72 // use the same value as in pdfViewer highlighting visual offset
}
this.syncToCodeInFlight = true
$http({
url: `/project/${ide.project_id}/sync/pdf`,
method: 'GET',
params: {
page: position.page + 1,
h: h.toFixed(2),
v: v.toFixed(2),
clsiserverid: ide.clsiServerId,
},
})
.then(response => {
this.syncToCodeInFlight = false
const { data } = response
if (
data.code != null &&
data.code.length > 0 &&
data.code[0].file !== ''
) {
const doc = ide.fileTreeManager.findEntityByPath(data.code[0].file)
if (doc == null) {
deferred.reject()
}
return deferred.resolve({ doc, line: data.code[0].line })
} else if (data.code[0].file === '') {
ide.$scope.sync_tex_error = true
setTimeout(() => (ide.$scope.sync_tex_error = false), 4000)
}
})
.catch(response => {
this.syncToCodeInFlight = false
const error = response.data
return deferred.reject(error)
})
return deferred.promise
},
}
})