فهرست منبع

Merge pull request #437 from sharelatex/pr-v2-splitters

Improve v2 splitters
Paulo Jorge Reis 8 سال پیش
والد
کامیت
8f7228d26e

+ 2 - 0
services/web/app/coffee/infrastructure/Features.coffee

@@ -16,5 +16,7 @@ module.exports = Features =
 				return Settings.accountMerge? and Settings.overleaf?
 			when 'rich-text'
 				return Settings.showRichText
+			when 'custom-togglers'
+				return Settings.overleaf?
 			else
 				throw new Error("unknown feature: #{feature}")

+ 3 - 0
services/web/app/views/project/editor.pug

@@ -62,6 +62,9 @@ block content
 					ng-hide="state.loading",
 					resize-on="layout:chat:resize",
 					minimum-restore-size-west="130"
+					custom-toggler-pane=hasFeature('custom-togglers') ? "'west'" : "false"
+					custom-toggler-msg-when-open=hasFeature('custom-togglers') ? "'" + translate("tooltip_hide_filetree") + "'" : "false"
+					custom-toggler-msg-when-closed=hasFeature('custom-togglers') ? "'" + translate("tooltip_show_filetree") + "'" : "false"
 				)
 					.ui-layout-west
 						include ./editor/file-tree

+ 3 - 1
services/web/app/views/project/editor/editor.pug

@@ -8,6 +8,9 @@ div.full-size(
 	initial-size-east="'50%'"
 	minimum-restore-size-east="300"
 	allow-overflow-on="'center'"
+	custom-toggler-pane=hasFeature('custom-togglers') ? "'east'" : "false"
+	custom-toggler-msg-when-open=hasFeature('custom-togglers') ? "'" + translate("tooltip_hide_pdf") + "'" : "false"
+	custom-toggler-msg-when-closed=hasFeature('custom-togglers') ? "'" + translate("tooltip_show_pdf") + "'" : "false"
 )
 	.ui-layout-center(
 		ng-controller="ReviewPanelController",
@@ -92,7 +95,6 @@ div.full-size(
 			ng-click="syncToCode()"
 		)
 			i.synctex-control-icon
-			
 div.full-size(
 	ng-if="ui.pdfLayout == 'flat'"
 	ng-show="ui.view == 'pdf'"

+ 59 - 1
services/web/public/coffee/ide/directives/layout.coffee

@@ -2,12 +2,17 @@ define [
 	"base"
 	"libs/jquery-layout"
 ], (App) ->
-	App.directive "layout", ["$parse", "ide", ($parse, ide) ->
+	App.directive "layout", ["$parse", "$compile", "ide", ($parse, $compile, ide) ->
 		return {
 			compile: () ->
 				pre: (scope, element, attrs) ->
 					name = attrs.layout
 
+					customTogglerPane = scope.$eval(attrs.customTogglerPane or "false")
+					customTogglerMsgWhenOpen = scope.$eval(attrs.customTogglerMsgWhenOpen or "false")
+					customTogglerMsgWhenClosed = scope.$eval(attrs.customTogglerMsgWhenClosed or "false")
+					hasCustomToggler = customTogglerPane != false and customTogglerMsgWhenOpen != false and customTogglerMsgWhenClosed != false
+
 					if attrs.spacingOpen?
 						spacingOpen = parseInt(attrs.spacingOpen, 10)
 					else
@@ -23,6 +28,10 @@ define [
 						spacing_closed: spacingClosed
 						slidable: false
 						enableCursorHotkey: false
+						onopen: (pane) => 
+							onPaneOpen(pane)
+						onclose: (pane) => 
+							onPaneClose(pane)
 						onresize: () =>
 							onInternalResize()
 						maskIframesOnResize: scope.$eval(
@@ -62,6 +71,15 @@ define [
 									right: state.east.size
 								})
 
+					repositionCustomToggler = () ->
+						if !customTogglerEl?
+							return
+						state = element.layout().readState()
+						positionAnchor = if customTogglerPane == "east" then "right" else "left"
+						paneState = state[customTogglerPane]
+						if paneState?
+							customTogglerEl.css(positionAnchor, if paneState.initClosed then 0 else paneState.size)
+	
 					resetOpenStates = () ->
 						state = element.layout().readState()
 						if attrs.openEast? and state.east?
@@ -73,6 +91,8 @@ define [
 						state = element.layout().readState()
 						scope.$broadcast "layout:#{name}:resize", state
 						repositionControls()
+						if hasCustomToggler
+							repositionCustomToggler()
 						resetOpenStates()
 						
 					oldWidth = element.width()
@@ -94,6 +114,44 @@ define [
 					if attrs.resizeOn?
 						scope.$on attrs.resizeOn, () -> onExternalResize()
 
+					if hasCustomToggler
+						state = element.layout().readState()
+						customTogglerScope = scope.$new()
+
+						customTogglerScope.isOpen = true
+
+						if state[customTogglerPane]?.initClosed == true
+							customTogglerScope.isOpen = false
+
+						customTogglerScope.tooltipMsgWhenOpen = customTogglerMsgWhenOpen
+						customTogglerScope.tooltipMsgWhenClosed = customTogglerMsgWhenClosed
+							
+						customTogglerScope.tooltipPlacement = if customTogglerPane == "east" then "left" else "right"
+						customTogglerScope.handleClick = () ->
+							element.layout().toggle(customTogglerPane)
+							repositionCustomToggler()
+						customTogglerEl = $compile("
+							<a href 
+							   class=\"custom-toggler #{ 'custom-toggler-' + customTogglerPane }\"
+							   ng-class=\"isOpen ? 'custom-toggler-open' : 'custom-toggler-closed'\"
+							   tooltip=\"{{ isOpen ? tooltipMsgWhenOpen : tooltipMsgWhenClosed }}\"
+							   tooltip-placement=\"{{ tooltipPlacement }}\"
+							   ng-click=\"handleClick()\">
+						")(customTogglerScope)
+						element.append(customTogglerEl)
+
+					onPaneOpen = (pane) ->
+						if !hasCustomToggler and pane != customTogglerPane
+							return
+						customTogglerEl.scope().$applyAsync () -> 
+							customTogglerEl.scope().isOpen = true
+
+					onPaneClose = (pane) ->
+						if !hasCustomToggler and pane != customTogglerPane
+							return
+						customTogglerEl.scope().$applyAsync () -> 
+							customTogglerEl.scope().isOpen = false
+
 					# Save state when exiting
 					$(window).unload () ->
 						ide.localStorage("layout.#{name}", element.layout().readState())

+ 73 - 70
services/web/public/stylesheets/app/editor.less

@@ -14,7 +14,7 @@
 @import "./editor/review-panel.less";
 
 @ui-layout-toggler-def-height: 50px;
-@ui-resizer-extra-hit-area: 8px;
+@ui-resizer-size: 7px;
 
 @keyframes blink {
 	0% { 
@@ -107,7 +107,7 @@
 			height: 0;
 			background: @editor-loading-logo-background-url no-repeat bottom / 100%;
 
-    		&::after {
+			&::after {
 				content: '';
 				position: absolute;
 				height: inherit;
@@ -116,7 +116,7 @@
 				left: 0;
 				background: @editor-loading-logo-foreground-url no-repeat bottom / 100%;
 				transition: height .5s;
-    		}
+			}
 		}
 		.loading-screen-label {
 			margin: 0;
@@ -302,40 +302,32 @@
 }
 
 .ui-layout-resizer when (@is-overleaf = true) {
-	margin-left: -(@ui-resizer-extra-hit-area) !important;
-	margin-right: -(@ui-resizer-extra-hit-area - 1px) !important;
-	padding-left: @ui-resizer-extra-hit-area !important;
-	padding-right: @ui-resizer-extra-hit-area !important;
 	z-index: 5 !important;
-	box-sizing: content-box;
-	background-image: linear-gradient(90deg, 
-		transparent,
-		transparent (@ui-resizer-extra-hit-area - 1px),
-		@editor-resizer-bg-color (@ui-resizer-extra-hit-area - 1px),
-		@editor-resizer-bg-color (@ui-resizer-extra-hit-area + 1px),
-		transparent (@ui-resizer-extra-hit-area + 1px),
-		transparent);
-
-	.ui-layout-toggler {
-		padding: 0 @ui-resizer-extra-hit-area !important;
-		background-image: linear-gradient(90deg, 
-			transparent,
-			transparent (@ui-resizer-extra-hit-area - 1px),
-			@editor-toggler-bg-color (@ui-resizer-extra-hit-area - 1px),
-			@editor-toggler-bg-color (@ui-resizer-extra-hit-area + 1px),
-			transparent (@ui-resizer-extra-hit-area + 1px),
-			transparent);
-
-		&:hover {
-			background-image: linear-gradient(90deg, 
-				transparent,
-				transparent (@ui-resizer-extra-hit-area - 2px),
-				@editor-toggler-hover-bg-color (@ui-resizer-extra-hit-area - 2px),
-				@editor-toggler-hover-bg-color (@ui-resizer-extra-hit-area + 2px),
-				transparent (@ui-resizer-extra-hit-area + 2px),
-				transparent);
+	width: @ui-resizer-size !important;
+	background-color: @editor-resizer-bg-color;
+	&.ui-layout-resizer-closed {
+		&::before,
+		&::after {
+			content: none;
 		}
 	}
+
+	&::before,
+	&::after {
+		content: '\2847';
+		display: block;
+		position: absolute;
+		text-align: center;
+		left: -2px;
+		-webkit-font-smoothing: antialiased;
+		width: 100%;
+		font-size: 24px;
+		top: 25%;
+		color: @ol-blue-gray-2;
+	}
+	&::after {
+		top: 75%;
+	}
 }
 
 .ui-layout-resizer-west.ui-layout-resizer-open, .ui-layout-resizer-east.ui-layout-resizer-closed {
@@ -353,54 +345,66 @@
 	}
 }
 
-.ui-layout-toggler.ui-layout-toggler-closed when (@is-overleaf = true) {
-	background-color: @editor-resizer-bg-color;
-	background-image: none;
-	line-height: @ui-layout-toggler-def-height;
-	
+.ui-layout-toggler when (@is-overleaf = true) {
+	display: none !important;
+}
+
+.custom-toggler when (@is-overleaf = true) {
+	position: absolute;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	width: @ui-resizer-size !important;;	
+	height: 50px;
+	margin-top: -25px;
+	top: 50%;
+	z-index: 6;
+	background-color: @editor-toggler-bg-color;
+
+	&:hover,
+	&:focus {
+		outline: none;
+		text-decoration: none;
+	}
+	// Increase hit area
 	&::before {
-		content: "\22EE"; // Vertical ellipsis
+		content: '';
 		display: block;
+		position: absolute;
+		top: 0;
+		right: -3px;
+		bottom: 0;
+		left: -3px;
+	}
+
+	&::after {
+    	font-family: FontAwesome;
+    	-webkit-font-smoothing: antialiased;
+		-moz-osx-font-smoothing: grayscale;
+    	font-size: 65%;
+    	font-weight: bold;
 		color: #FFF;
-		font-weight: 700;
-		font-size: @font-size-h2;
-		width: @ui-resizer-extra-hit-area / 2;
+		user-select: none;
+		pointer-events: none;
 	}
+
 	&:hover {
 		background-color: @editor-toggler-hover-bg-color;
-		background-image: none;
-	}
-	.ui-layout-resizer-west > & {
-		border-radius: 0 @border-radius-base @border-radius-base 0;
-		&::before {
-			margin-left: -2px;
-		}
-	}
-	.ui-layout-resizer-east > & {
-		border-radius: @border-radius-base 0 0 @border-radius-base;
-		&::before {
-			margin-left: (-1 - @ui-resizer-extra-hit-area);
-		}
 	}
 }
-
-.ui-layout-toggler-east when (@is-overleaf = true) {
-	&.ui-layout-toggler-open {
-		cursor: e-resize !important
+	.custom-toggler-east::after {
+		content: '\f105';
 	}
-	&.ui-layout-toggler-closed {
-		cursor: w-resize !important
+	.custom-toggler-west::after {
+		content: '\f104';
 	}
-}
 
-.ui-layout-toggler-west when (@is-overleaf = true) {
-	&.ui-layout-toggler-open {
-		cursor: w-resize !important
+	.custom-toggler-closed.custom-toggler-east::after {
+		content: '\f104';
 	}
-	&.ui-layout-toggler-closed {
-		cursor: e-resize !important
+	.custom-toggler-closed.custom-toggler-west::after {
+		content: '\f105';
 	}
-}
 
 .ui-layout-resizer-dragging {
 	background-color: @editor-resizer-bg-color-dragging;
@@ -624,4 +628,3 @@
 	height: auto;
 	border-bottom: 1px solid @modal-header-border-color;
 }
-

+ 1 - 1
services/web/public/stylesheets/app/editor/pdf.less

@@ -270,7 +270,7 @@
 }
 
 .synctex-controls when (@is-overleaf = true) {
-	margin-right: -11px;
+	margin-right: -8px;
 }
 	.synctex-control {
 		display: block;

+ 3 - 3
services/web/public/stylesheets/core/ol-variables.less

@@ -227,9 +227,9 @@
 @file-tree-droppable-bg-color   : tint(@ol-green, 5%);
 
 // Editor resizers
-@editor-resizer-bg-color          : @ol-blue-gray-6;
-@editor-resizer-bg-color-dragging : transparent;
-@editor-toggler-bg-color          : @ol-blue-gray-2;
+@editor-resizer-bg-color          : @ol-blue-gray-5;
+@editor-resizer-bg-color-dragging : @ol-blue-gray-5;
+@editor-toggler-bg-color          : darken(@ol-blue-gray-2, 15%);
 @editor-toggler-hover-bg-color    : @ol-green;
 @synctex-controls-z-index         : 6;
 @synctex-controls-padding         : 0;