Admin Chat Preview: fix for widescreen & add animation
Turns out that the chat preview was broken on big screens. The website screenshot didn’t span the whole width and the chat was getting cut off. Fixes: - preserve 16:10 browser aspect ratio - rename zoom to 1:1 - hide 1:1 mode on big screens that don’t need it - scale the website screenshot to the full width - scale the website screenshot in 1:1 mode with the chat - make color picker work with changes - use dynamic height in the form preview
This commit is contained in:
parent
577bb5f723
commit
5239c83e71
4 changed files with 143 additions and 99 deletions
|
@ -5,7 +5,7 @@ class App.ChannelChat extends App.ControllerSubContent
|
|||
'change .js-params': 'updateParams'
|
||||
'input .js-params': 'updateParams'
|
||||
'submit .js-demo-head': 'onUrlSubmit'
|
||||
'click .js-selectBrowserWidth': 'selectBrowserWidth'
|
||||
'click .js-selectBrowserSize': 'selectBrowserSize'
|
||||
'click .js-swatch': 'usePaletteColor'
|
||||
'click .js-toggle-chat': 'toggleChat'
|
||||
'change .js-chatSetting input': 'toggleChatSetting'
|
||||
|
@ -104,8 +104,7 @@ class App.ChannelChat extends App.ControllerSubContent
|
|||
]
|
||||
|
||||
isOpen: true
|
||||
browserWidth: 1280
|
||||
browserWidthMax: 1280
|
||||
browserSize: 'desktop'
|
||||
previewUrl: ''
|
||||
previewScale: 1
|
||||
|
||||
|
@ -167,45 +166,33 @@ class App.ChannelChat extends App.ControllerSubContent
|
|||
$(window).off 'resize.chat-designer'
|
||||
@website.off('click.eyedropper')
|
||||
|
||||
selectBrowserWidth: (event) =>
|
||||
tab = $(event.target).closest('[data-value]')
|
||||
selectBrowserSize: (event) =>
|
||||
tab = $(event.target).closest('[data-size]')
|
||||
|
||||
# select tab
|
||||
tab.addClass('is-selected').siblings().removeClass('is-selected')
|
||||
@browserWidth = tab.attr('data-value')
|
||||
@browserSize = tab.attr('data-size')
|
||||
@updatePreview()
|
||||
|
||||
updatePreview: (animate = true) =>
|
||||
width = parseInt @browserWidth, 10
|
||||
|
||||
# reset zoom
|
||||
@chat
|
||||
.removeClass('is-fullscreen')
|
||||
.toggleClass('no-transition', !animate)
|
||||
.css 'transform', "translateY(#{ @getChatOffset() }px)"
|
||||
@browser.css('width', '')
|
||||
@website.css
|
||||
transform: ''
|
||||
width: ''
|
||||
height: ''
|
||||
@browser.attr('data-size', @browserSize)
|
||||
@previewScale = 1
|
||||
|
||||
return if @browserWidth is 'fit'
|
||||
|
||||
if width < @el.width() && width == 375
|
||||
@chat.addClass('is-fullscreen').css 'transform', "translateY(#{ @getChatOffset(true) }px)"
|
||||
@browser.css('width', "#{ width }px")
|
||||
else
|
||||
if @el.width() > width && width == @browserWidthMax
|
||||
@previewScale = 1
|
||||
else
|
||||
@previewScale = @el.width()/width
|
||||
|
||||
@chat.css 'transform', "translateY(#{ @getChatOffset() * @previewScale }px) scale(#{ @previewScale })"
|
||||
@website.css
|
||||
transform: "scale(#{ @previewScale })"
|
||||
width: @el.width() / @previewScale
|
||||
height: @browserBody.height() / @previewScale
|
||||
switch @browserSize
|
||||
when 'mobile'
|
||||
@chat.addClass('is-fullscreen').css 'transform', "translateY(#{ @getChatOffset(true) }px)"
|
||||
when '1:1'
|
||||
@previewScale = Math.max(1, 1280/@el.width())
|
||||
@website.css 'transform', "scale(#{ @previewScale })"
|
||||
when 'desktop'
|
||||
scale = Math.min(1, @el.width()/1280) # don't use it for the previewScale (used for the color picker)
|
||||
@website.css 'transform', ''
|
||||
@chat.css 'transform', "translateY(#{ @getChatOffset() * scale }px) scale(#{ scale })"
|
||||
|
||||
getChatOffset: (fullscreen) ->
|
||||
return 0 if @isOpen
|
||||
|
@ -296,8 +283,11 @@ class App.ChannelChat extends App.ControllerSubContent
|
|||
@eyedropper.addClass('is-active')
|
||||
|
||||
onColorPicked: (event) =>
|
||||
x = event.pageX - @website.offset().left
|
||||
y = event.pageY - @website.offset().top
|
||||
website_x = @website.position().left
|
||||
website_y = @website.position().top
|
||||
|
||||
relative_x = event.pageX - @browserBody.offset().left
|
||||
relative_y = event.pageY - @browserBody.offset().top
|
||||
|
||||
image = new Image()
|
||||
image.src = @_screenshotSource
|
||||
|
@ -305,11 +295,11 @@ class App.ChannelChat extends App.ControllerSubContent
|
|||
canvas = document.createElement('canvas')
|
||||
ctx = canvas.getContext('2d')
|
||||
|
||||
canvas.width = image.width
|
||||
canvas.height = image.height
|
||||
canvas.width = @browserBody.width()
|
||||
canvas.height = @browserBody.height()
|
||||
|
||||
ctx.drawImage(image, 0, 0, @previewScale * canvas.width, @previewScale * canvas.height)
|
||||
pixels = ctx.getImageData(x, y, 1, 1).data
|
||||
ctx.drawImage(image, website_x, website_y, @website.width() * @previewScale, @website.width() * @previewScale)
|
||||
pixels = ctx.getImageData(relative_x, relative_y, 1, 1).data
|
||||
|
||||
@colorField.val("rgb(#{pixels.slice(0,3).join(',')})").trigger('change')
|
||||
|
||||
|
|
|
@ -19,62 +19,64 @@
|
|||
<div class="form-group">
|
||||
<label class="formGroup-label"><%- @T('Preview Width') %></label>
|
||||
<div class="control">
|
||||
<div class="select-tabs js-selectBrowserWidth">
|
||||
<div class="tab" data-value="375">iPhone 6</div>
|
||||
<div class="tab" data-value="fit">1:1</div>
|
||||
<div class="tab is-selected" data-value="1280">MacBook</div>
|
||||
<div class="select-tabs js-selectBrowserSize">
|
||||
<div class="tab" data-size="mobile">Mobile</div>
|
||||
<div class="tab" data-size="1:1">1:1</div>
|
||||
<div class="tab is-selected" data-size="desktop">Desktop</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label for="preview-iframe" class="formGroup-label"><%- @T('Preview') %></label>
|
||||
<div class="browser chat-demo js-browser">
|
||||
<form class="browser-head js-demo-head" novalidate>
|
||||
<div class="browser-input">
|
||||
<input type="url" class="js-testurl-input" id="preview-iframe" value="<%= @previewUrl %>" placeholder="www.zammad.org">
|
||||
<div class="loading icon small muted"></div>
|
||||
</div>
|
||||
<input type="submit" class="btn" value="<%- @Ti('Load') %>">
|
||||
</form>
|
||||
<div class="browser-body js-browserBody">
|
||||
<div class="browser-website js-website">
|
||||
<img class="js-screenshot">
|
||||
</div>
|
||||
<style>@import "/assets/chat/chat.css";</style>
|
||||
<div class="chat-demo-animationHolder">
|
||||
<div class="js-chat zammad-chat zammad-chat-is-open zammad-chat-is-loaded zammad-chat-is-shown is-open">
|
||||
<div class="zammad-chat-header js-toggle-chat js-backgroundColor js-chatHeader">
|
||||
<div class="zammad-chat-header-controls">
|
||||
<span class="zammad-chat-agent-status" data-status="online"><%- @T('Online') %></span>
|
||||
<span class="zammad-chat-header-icon">
|
||||
<svg class="zammad-chat-header-icon-open" viewBox="0 0 13 7"><path d="M10.807 7l1.4-1.428-5-4.9L6.5-.02l-.7.7-4.9 4.9 1.414 1.413L6.5 2.886 10.807 7z" fill-rule="evenodd"></path></svg>
|
||||
<svg class="zammad-chat-header-icon-close" viewBox="0 0 13 13"><path d="m2.241.12l-2.121 2.121 4.243 4.243-4.243 4.243 2.121 2.121 4.243-4.243 4.243 4.243 2.121-2.121-4.243-4.243 4.243-4.243-2.121-2.121-4.243 4.243-4.243-4.243" fill-rule="evenodd"></path></svg>
|
||||
</span>
|
||||
<div class="browser chat-demo js-browser" data-size="desktop">
|
||||
<div class="browser-ratio">
|
||||
<form class="browser-head js-demo-head" novalidate>
|
||||
<div class="browser-input">
|
||||
<input type="url" class="js-testurl-input" id="preview-iframe" value="<%= @previewUrl %>" placeholder="www.zammad.org">
|
||||
<div class="loading icon small muted"></div>
|
||||
</div>
|
||||
<input type="submit" class="btn" value="<%- @Ti('Load') %>">
|
||||
</form>
|
||||
<div class="browser-body js-browserBody">
|
||||
<div class="browser-website js-website">
|
||||
<img class="browser-website-background js-screenshot">
|
||||
</div>
|
||||
<style>@import "/assets/chat/chat.css";</style>
|
||||
<div class="chat-demo-animationHolder">
|
||||
<div class="js-chat zammad-chat zammad-chat-is-open zammad-chat-is-loaded zammad-chat-is-shown is-open">
|
||||
<div class="zammad-chat-header js-toggle-chat js-backgroundColor js-chatHeader">
|
||||
<div class="zammad-chat-header-controls">
|
||||
<span class="zammad-chat-agent-status" data-status="online"><%- @T('Online') %></span>
|
||||
<span class="zammad-chat-header-icon">
|
||||
<svg class="zammad-chat-header-icon-open" viewBox="0 0 13 7"><path d="M10.807 7l1.4-1.428-5-4.9L6.5-.02l-.7.7-4.9 4.9 1.414 1.413L6.5 2.886 10.807 7z" fill-rule="evenodd"></path></svg>
|
||||
<svg class="zammad-chat-header-icon-close" viewBox="0 0 13 13"><path d="m2.241.12l-2.121 2.121 4.243 4.243-4.243 4.243 2.121 2.121 4.243-4.243 4.243 4.243 2.121-2.121-4.243-4.243 4.243-4.243-2.121-2.121-4.243 4.243-4.243-4.243" fill-rule="evenodd"></path></svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="zammad-chat-agent">
|
||||
<img class="zammad-chat-agent-avatar" src="/assets/images/chat-demo-avatar.png">
|
||||
<span class="zammad-chat-agent-sentence">
|
||||
<span class="zammad-chat-agent-name"><%- @T('John Smith') %></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="zammad-chat-welcome zammad-chat-is-hidden">
|
||||
<svg class="zammad-chat-icon" viewBox="0 0 24 24"><path d="M2 5C2 4 3 3 4 3h16c1 0 2 1 2 2v10C22 16 21 17 20 17H4C3 17 2 16 2 15V5zM12 17l6 4v-4h-6z" fill-rule="evenodd"></path></svg>
|
||||
<span class="zammad-chat-welcome-text js-chat-welcome"><strong>Chat</strong> with us!</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="zammad-chat-agent">
|
||||
<img class="zammad-chat-agent-avatar" src="/assets/images/chat-demo-avatar.png">
|
||||
<span class="zammad-chat-agent-sentence">
|
||||
<span class="zammad-chat-agent-name"><%- @T('John Smith') %></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="zammad-chat-welcome zammad-chat-is-hidden">
|
||||
<svg class="zammad-chat-icon" viewBox="0 0 24 24"><path d="M2 5C2 4 3 3 4 3h16c1 0 2 1 2 2v10C22 16 21 17 20 17H4C3 17 2 16 2 15V5zM12 17l6 4v-4h-6z" fill-rule="evenodd"></path></svg>
|
||||
<span class="zammad-chat-welcome-text js-chat-welcome"><strong>Chat</strong> with us!</span>
|
||||
<div class="zammad-chat-body">
|
||||
<div class="zammad-chat-timestamp"><strong><%- @T('today') %></strong> 14:45</div>
|
||||
<div class="zammad-chat-message zammad-chat-message--customer">
|
||||
<span class="zammad-chat-message-body js-backgroundColor"><%- @T('Hello! I need help with your product.') %></span>
|
||||
</div>
|
||||
<div class="zammad-chat-message zammad-chat-message--agent">
|
||||
<span class="zammad-chat-message-body"><%- @T('Hi! Which one of our products?') %></span>
|
||||
</div>
|
||||
</div>
|
||||
<form class="zammad-chat-controls">
|
||||
<textarea class="zammad-chat-input" rows="1" placeholder="Ihre Nachricht..."></textarea>
|
||||
<button type="submit" class="zammad-chat-button zammad-chat-send js-backgroundColor"><%- @T('Send') %></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="zammad-chat-body">
|
||||
<div class="zammad-chat-timestamp"><strong><%- @T('today') %></strong> 14:45</div>
|
||||
<div class="zammad-chat-message zammad-chat-message--customer">
|
||||
<span class="zammad-chat-message-body js-backgroundColor"><%- @T('Hello! I need help with your product.') %></span>
|
||||
</div>
|
||||
<div class="zammad-chat-message zammad-chat-message--agent">
|
||||
<span class="zammad-chat-message-body"><%- @T('Hi! Which one of our products?') %></span>
|
||||
</div>
|
||||
</div>
|
||||
<form class="zammad-chat-controls">
|
||||
<textarea class="zammad-chat-input" rows="1" placeholder="Ihre Nachricht..."></textarea>
|
||||
<button type="submit" class="zammad-chat-button zammad-chat-send js-backgroundColor"><%- @T('Send') %></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -117,12 +117,14 @@
|
|||
|
||||
<label class="formGroup-label"><%- @T('Preview') %></label>
|
||||
|
||||
<div class="browser form-demo js-browser">
|
||||
<div class="browser-body js-browserBody">
|
||||
<div class="browser-website centered vertical fit">
|
||||
<div class="btn js-formBtn"><%- @T('Feedback') %></div>
|
||||
<div class="js-formInline" style="width: 300px;"></div>
|
||||
<script id="zammad_form_script" src="/assets/form/form.js"></script>
|
||||
<div class="browser js-browser">
|
||||
<div class="browser-ratio">
|
||||
<div class="browser-body js-browserBody">
|
||||
<div class="browser-website centered vertical fit">
|
||||
<div class="btn js-formBtn"><%- @T('Feedback') %></div>
|
||||
<div class="js-formInline" style="width: 300px;"></div>
|
||||
<script id="zammad_form_script" src="/assets/form/form.js"></script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10040,32 +10040,82 @@ output {
|
|||
|
||||
.browser {
|
||||
margin: 0 0 20px;
|
||||
border: 1px solid hsl(0,0%,90%);
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
transition: 500ms;
|
||||
width: 100%;
|
||||
|
||||
&[data-size] {
|
||||
padding-bottom: 65%; // 16:10 aspect ratio;
|
||||
|
||||
.browser-ratio {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
transition: 500ms;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.browser-body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-size="mobile"] .browser-ratio {
|
||||
width: 375px;
|
||||
}
|
||||
|
||||
&-ratio {
|
||||
border: 1px solid hsl(0,0%,90%);
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: #{1280 + $sidebarWidth + $navigationWidth}) {
|
||||
// hide 1:1 button when it gets inrelevant
|
||||
[data-size="1:1"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.browser[data-size="mobile"] .browser-ratio {
|
||||
width: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
.browser-body {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 450px;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
|
||||
&-inner {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.browser-website {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
transform-origin: left top;
|
||||
transform-origin: right bottom;
|
||||
transition: 500ms;
|
||||
overflow: hidden;
|
||||
|
||||
&.is-picking {
|
||||
cursor: image_url("/assets/images/eyedropper.gif") 0 15, auto;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
vertical-align: bottom;
|
||||
&-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: left top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue