mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #3111 from overleaf/pr-file-outline-out-of-beta
File outline out of beta GitOrigin-RevId: 64fa6554813b1d0ceff2b567922651509badecc7
This commit is contained in:
parent
aec9de8e1b
commit
7fc0f88996
13 changed files with 133 additions and 72 deletions
|
@ -100,15 +100,19 @@ div.full-size(
|
|||
tooltip-placement="right"
|
||||
tooltip-append-to-body="true"
|
||||
ng-click="syncToPdf()"
|
||||
ng-disabled="syncToPdfInFlight"
|
||||
)
|
||||
i.synctex-control-icon
|
||||
i.synctex-control-icon(ng-show="!syncToPdfInFlight")
|
||||
i.synctex-spin-icon.fa.fa-refresh.fa-spin(ng-show="syncToPdfInFlight")
|
||||
a.btn.btn-default.btn-xs.synctex-control.synctex-control-goto-code(
|
||||
tooltip-html="'"+translate('go_to_pdf_location_in_code', {}, true)+"'"
|
||||
tooltip-placement="right"
|
||||
tooltip-append-to-body="true"
|
||||
ng-click="syncToCode()"
|
||||
ng-disabled="syncToCodeInFlight"
|
||||
)
|
||||
i.synctex-control-icon
|
||||
i.synctex-control-icon(ng-show="!syncToCodeInFlight")
|
||||
i.synctex-spin-icon.fa.fa-refresh.fa-spin(ng-show="syncToCodeInFlight")
|
||||
|
||||
div.full-size(
|
||||
ng-if="ui.pdfLayout == 'flat'"
|
||||
|
|
|
@ -2,13 +2,13 @@ aside.editor-sidebar.full-size(
|
|||
ng-controller="FileTreeController"
|
||||
ng-class="{ 'multi-selected': multiSelectedCount > 0 }"
|
||||
ng-show="ui.view != 'history' || !history.isV2"
|
||||
vertical-resizable-panes=user.betaProgram && "outline-resizer"
|
||||
vertical-resizable-panes-toggled-externally-on=user.betaProgram && "outline-toggled"
|
||||
vertical-resizable-panes-min-size=user.betaProgram && "32"
|
||||
vertical-resizable-panes-max-size=user.betaProgram && "75%"
|
||||
vertical-resizable-panes="outline-resizer"
|
||||
vertical-resizable-panes-toggled-externally-on="outline-toggled"
|
||||
vertical-resizable-panes-min-size="32"
|
||||
vertical-resizable-panes-max-size="75%"
|
||||
)
|
||||
.file-tree(
|
||||
vertical-resizable-top=user.betaProgram
|
||||
vertical-resizable-top
|
||||
)
|
||||
.toolbar.toolbar-filetree(ng-if="permissions.write")
|
||||
a(
|
||||
|
@ -99,20 +99,19 @@ aside.editor-sidebar.full-size(
|
|||
|
||||
span {{ entity.name }}
|
||||
|
||||
if user.betaProgram
|
||||
.outline-container(
|
||||
vertical-resizable-bottom
|
||||
ng-controller="OutlineController"
|
||||
.outline-container(
|
||||
vertical-resizable-bottom
|
||||
ng-controller="OutlineController"
|
||||
)
|
||||
outline-pane(
|
||||
is-tex-file="isTexFile"
|
||||
outline="outline"
|
||||
project-id="project_id"
|
||||
jump-to-line="jumpToLine"
|
||||
on-toggle="onToggle"
|
||||
event-tracking="eventTracking"
|
||||
highlighted-line="highlightedLine"
|
||||
)
|
||||
outline-pane(
|
||||
is-tex-file="isTexFile"
|
||||
outline="outline"
|
||||
project-id="project_id"
|
||||
jump-to-line="jumpToLine"
|
||||
on-toggle="onToggle"
|
||||
event-tracking="eventTracking"
|
||||
highlighted-line="highlightedLine"
|
||||
)
|
||||
|
||||
|
||||
script(type='text/ng-template', id='entityListItemTemplate')
|
||||
|
@ -156,8 +155,7 @@ script(type='text/ng-template', id='entityListItemTemplate')
|
|||
dropdown,
|
||||
ng-if="permissions.write"
|
||||
)
|
||||
a.dropdown-toggle(href, dropdown-toggle, stop-propagation="click")
|
||||
i.fa.fa-chevron-down
|
||||
a.dropdown-toggle.file-tree-dropdown-toggle(href, dropdown-toggle, stop-propagation="click")
|
||||
|
||||
ul.dropdown-menu.dropdown-menu-right
|
||||
li
|
||||
|
@ -214,7 +212,7 @@ script(type='text/ng-template', id='entityListItemTemplate')
|
|||
)
|
||||
i.fa.fa-fw.toggle(
|
||||
ng-if="entity.type == 'folder'"
|
||||
ng-class="{'fa-chevron-right': !expanded, 'fa-chevron-down': expanded}"
|
||||
ng-class="{'fa-angle-right': !expanded, 'fa-angle-down': expanded}"
|
||||
ng-click="toggleExpanded()"
|
||||
)
|
||||
|
||||
|
@ -245,8 +243,7 @@ script(type='text/ng-template', id='entityListItemTemplate')
|
|||
dropdown,
|
||||
ng-if="permissions.write"
|
||||
)
|
||||
a.dropdown-toggle(href, dropdown-toggle, stop-propagation="click")
|
||||
i.fa.fa-chevron-down
|
||||
a.dropdown-toggle.file-tree-dropdown-toggle(href, dropdown-toggle, stop-propagation="click")
|
||||
|
||||
ul.dropdown-menu.dropdown-menu-right
|
||||
li
|
||||
|
|
|
@ -139,8 +139,8 @@ export default (EditorManager = (function() {
|
|||
sl_console.log(`[openDoc] Opening ${doc.id}`)
|
||||
this.$scope.ui.view = 'editor'
|
||||
|
||||
const done = () => {
|
||||
this.$scope.$broadcast('doc:after-opened')
|
||||
const done = isNewDoc => {
|
||||
this.$scope.$broadcast('doc:after-opened', { isNewDoc })
|
||||
if (options.gotoLine != null) {
|
||||
// allow Ace to display document before moving, delay until next tick
|
||||
// added delay to make this happen later that gotoStoredPosition in
|
||||
|
@ -163,7 +163,7 @@ export default (EditorManager = (function() {
|
|||
// automatically update the file tree whenever the file is opened
|
||||
this.ide.fileTreeManager.selectEntity(doc)
|
||||
this.$scope.$apply(() => {
|
||||
return done()
|
||||
return done(false)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ export default (EditorManager = (function() {
|
|||
return this.$scope.$apply(() => {
|
||||
this.$scope.editor.opening = false
|
||||
this.$scope.editor.sharejs_doc = sharejs_doc
|
||||
return done()
|
||||
return done(true)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -18,9 +18,17 @@ class OutlineManager {
|
|||
this.ignoreNextScroll = false
|
||||
this.ignoreNextCursorUpdate = false
|
||||
|
||||
scope.$on('doc:after-opened', () => {
|
||||
scope.$on('doc:after-opened', (ev, { isNewDoc }) => {
|
||||
if (isNewDoc) {
|
||||
// if a new doc is opened a cursor updates will be triggered before the
|
||||
// content is loaded. We have to ignore it or the outline highlight
|
||||
// will be incorrect. This doesn't happen when `doc:after-opened` is
|
||||
// fired without a new doc opened.
|
||||
this.ignoreNextCursorUpdate = true
|
||||
}
|
||||
// always ignore the next scroll update so the cursor update takes
|
||||
// precedence
|
||||
this.ignoreNextScroll = true
|
||||
this.ignoreNextCursorUpdate = true
|
||||
this.shareJsDoc = scope.editor.sharejs_doc
|
||||
this.isTexFile = isValidTeXFile(scope.editor.open_doc_name)
|
||||
this.updateOutline()
|
||||
|
|
|
@ -3,6 +3,14 @@ import PropTypes from 'prop-types'
|
|||
import classNames from 'classnames'
|
||||
import OutlineList from './OutlineList'
|
||||
|
||||
function getChildrenLines(children) {
|
||||
return (children || [])
|
||||
.map(child => {
|
||||
return getChildrenLines(child.children).concat(child.line)
|
||||
})
|
||||
.flat()
|
||||
}
|
||||
|
||||
function OutlineItem({ outlineItem, jumpToLine, highlightedLine }) {
|
||||
const [expanded, setExpanded] = useState(true)
|
||||
const titleElementRef = createRef()
|
||||
|
@ -17,8 +25,13 @@ function OutlineItem({ outlineItem, jumpToLine, highlightedLine }) {
|
|||
'fa-angle-right': !expanded
|
||||
})
|
||||
|
||||
const hasHighlightedChild =
|
||||
!expanded &&
|
||||
getChildrenLines(outlineItem.children).includes(highlightedLine)
|
||||
|
||||
const itemLinkClasses = classNames('outline-item-link', {
|
||||
'outline-item-link-highlight': highlightedLine === outlineItem.line
|
||||
'outline-item-link-highlight':
|
||||
highlightedLine === outlineItem.line || hasHighlightedChild
|
||||
})
|
||||
|
||||
function handleExpandCollapseClick() {
|
||||
|
|
|
@ -55,19 +55,19 @@ function OutlinePane({
|
|||
>
|
||||
<i className={expandCollapseIconClasses} />
|
||||
<h4 className="outline-header-name">File outline</h4>
|
||||
<OverlayTrigger placement="top" overlay={tooltip} delayHide={100}>
|
||||
<a
|
||||
href="/beta/participate"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="outline-header-beta-badge"
|
||||
>
|
||||
<span className="sr-only">
|
||||
The File outline is a beta feature. Click here to manage your
|
||||
beta program membership.
|
||||
</span>
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
{expanded ? (
|
||||
<OverlayTrigger placement="top" overlay={tooltip} delayHide={100}>
|
||||
<a
|
||||
href="https://forms.gle/8N1iSS9rkgmpFDHY6"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="outline-header-info-badge"
|
||||
onClick={ev => ev.stopPropagation()}
|
||||
>
|
||||
<span className="sr-only">{infoContent}</span>
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
) : null}
|
||||
</button>
|
||||
</header>
|
||||
{expanded && isTexFile ? (
|
||||
|
@ -83,11 +83,13 @@ function OutlinePane({
|
|||
)
|
||||
}
|
||||
|
||||
const tooltip = (
|
||||
<Tooltip id="outline-beta-badge-tooltip">
|
||||
The <strong>File outline</strong> is a beta feature.
|
||||
</Tooltip>
|
||||
const infoContent = (
|
||||
<>
|
||||
The <strong>File outline</strong> is a new feature. Click the icon to give
|
||||
feedback.
|
||||
</>
|
||||
)
|
||||
const tooltip = <Tooltip id="outline-info-tooltip">{infoContent}</Tooltip>
|
||||
|
||||
OutlinePane.propTypes = {
|
||||
isTexFile: PropTypes.bool.isRequired,
|
||||
|
|
|
@ -21,7 +21,7 @@ function OutlineRoot({ outline, jumpToLine, highlightedLine }) {
|
|||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Know more about the file outline
|
||||
Find out more about the file outline
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -973,6 +973,8 @@ App.factory('synctex', function(ide, $http, $q) {
|
|||
|
||||
App.controller('PdfSynctexController', function($scope, synctex, ide) {
|
||||
this.cursorPosition = null
|
||||
$scope.syncToPdfInFlight = false
|
||||
$scope.syncToCodeInFlight = false
|
||||
ide.$scope.$on('cursor:editor:update', (event, cursorPosition) => {
|
||||
this.cursorPosition = cursorPosition
|
||||
})
|
||||
|
@ -981,14 +983,19 @@ App.controller('PdfSynctexController', function($scope, synctex, ide) {
|
|||
if (this.cursorPosition == null) {
|
||||
return
|
||||
}
|
||||
synctex.syncToPdf(this.cursorPosition).then(highlights => {
|
||||
$scope.pdf.highlights = highlights
|
||||
})
|
||||
$scope.syncToPdfInFlight = true
|
||||
synctex
|
||||
.syncToPdf(this.cursorPosition)
|
||||
.then(highlights => {
|
||||
$scope.pdf.highlights = highlights
|
||||
})
|
||||
.finally(() => ($scope.syncToPdfInFlight = false))
|
||||
}
|
||||
|
||||
ide.$scope.$on('cursor:editor:syncToPdf', $scope.syncToPdf)
|
||||
|
||||
$scope.syncToCode = function() {
|
||||
$scope.syncToCodeInFlight = true
|
||||
synctex
|
||||
.syncToCode($scope.pdf.position, {
|
||||
includeVisualOffset: true,
|
||||
|
@ -998,6 +1005,7 @@ App.controller('PdfSynctexController', function($scope, synctex, ide) {
|
|||
const { doc, line } = data
|
||||
ide.editorManager.openDoc(doc, { gotoLine: line })
|
||||
})
|
||||
.finally(() => ($scope.syncToCodeInFlight = false))
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -142,10 +142,30 @@
|
|||
i.toggle {
|
||||
width: 24px;
|
||||
padding: 6px;
|
||||
font-size: 0.7rem;
|
||||
font-size: 16px;
|
||||
color: @file-tree-item-toggle-color;
|
||||
}
|
||||
|
||||
.file-tree-dropdown-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
white-space: pre;
|
||||
line-height: 6px;
|
||||
font-size: 20px;
|
||||
height: 100%;
|
||||
padding: 0 12px 0 18px;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
&::before {
|
||||
content: '\00B7\A\00B7\A\00B7';
|
||||
margin-top: -4px;
|
||||
}
|
||||
}
|
||||
|
||||
&.multi-selected {
|
||||
> .entity {
|
||||
> .entity-name {
|
||||
|
@ -172,9 +192,6 @@
|
|||
.dropdown {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
> a {
|
||||
padding: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.rename-input {
|
||||
|
@ -234,7 +251,8 @@
|
|||
.fake-full-width-bg(@file-tree-item-selected-bg);
|
||||
|
||||
.entity-menu-toggle {
|
||||
display: inline;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,19 +62,21 @@
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.outline-header-beta-badge {
|
||||
.outline-header-info-badge {
|
||||
display: inline-block;
|
||||
border-radius: @border-radius-base;
|
||||
background-color: @orange;
|
||||
width: @outline-h-rhythm * 0.75;
|
||||
height: @outline-v-rhythm * 0.75;
|
||||
line-height: @outline-v-rhythm * 0.75;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
background-color: @info-badge-bg;
|
||||
font-family: @font-family-serif;
|
||||
color: #fff;
|
||||
font-style: italic;
|
||||
border-radius: @outline-h-rhythm * 0.375;
|
||||
|
||||
&::before {
|
||||
content: 'β';
|
||||
content: 'i';
|
||||
}
|
||||
|
||||
&:hover,
|
||||
|
@ -174,6 +176,7 @@
|
|||
border-radius: @border-radius-base;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: left;
|
||||
&:hover,
|
||||
&:focus {
|
||||
outline: 0;
|
||||
|
|
|
@ -233,6 +233,11 @@
|
|||
background-color: fade(@btn-default-bg, 80%);
|
||||
transition: background 0.15s ease;
|
||||
|
||||
&[disabled] {
|
||||
opacity: 1;
|
||||
background-color: fade(@btn-default-bg, 60%);
|
||||
}
|
||||
|
||||
> .synctex-control-icon {
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 FontAwesome;
|
||||
|
@ -241,6 +246,10 @@
|
|||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
> .synctex-spin-icon {
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.synctex-control-goto-pdf > .synctex-control-icon {
|
||||
|
|
|
@ -325,8 +325,7 @@ ul.folders-menu {
|
|||
}
|
||||
> li.folders-menu-item-with-tooltip {
|
||||
> a {
|
||||
padding-right: 1.5 * @folders-menu-item-h-padding +
|
||||
@folders-menu-tooltip-size;
|
||||
padding-right: 1.5 * @folders-menu-item-h-padding + @info-badge-size;
|
||||
}
|
||||
}
|
||||
> li > a.small {
|
||||
|
@ -414,15 +413,15 @@ ul.folders-menu {
|
|||
position: absolute;
|
||||
top: 50%;
|
||||
right: @folders-menu-item-h-padding;
|
||||
width: @folders-menu-tooltip-size;
|
||||
height: @folders-menu-tooltip-size;
|
||||
margin-top: -(floor(@folders-menu-tooltip-size / 2));
|
||||
line-height: @folders-menu-tooltip-size;
|
||||
background-color: @folders-menu-tooltip-bg;
|
||||
width: @info-badge-size;
|
||||
height: @info-badge-size;
|
||||
margin-top: -(floor(@info-badge-size / 2));
|
||||
line-height: @info-badge-size;
|
||||
background-color: @info-badge-bg;
|
||||
font-family: @font-family-serif;
|
||||
color: #fff;
|
||||
font-style: italic;
|
||||
border-radius: ceil(@folders-menu-tooltip-size / 2);
|
||||
border-radius: ceil(@info-badge-size / 2);
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
@media (min-width: @screen-sm-min) {
|
||||
|
|
|
@ -956,8 +956,8 @@
|
|||
@folders-tag-border-color: @folders-tag-menu-color;
|
||||
@folders-tag-menu-active-hover: rgba(0, 0, 0, 0.1);
|
||||
@folders-tag-menu-hover: rgba(0, 0, 0, 0.1);
|
||||
@folders-menu-tooltip-size: 21px;
|
||||
@folders-menu-tooltip-bg: @ol-blue;
|
||||
@info-badge-size: 21px;
|
||||
@info-badge-bg: @ol-blue;
|
||||
// Progress bars
|
||||
@progress-border-radius: @line-height-computed;
|
||||
@progress-border-width: 0;
|
||||
|
|
Loading…
Reference in a new issue