* VRFS-560, VRFS-898, VRFS-597, VRFS-1153, VRFS-1154 - all ftue related fixes and improvements in user behavior. make new ftue show up everywhere instead of new ftue

This commit is contained in:
Seth Call 2014-02-21 22:02:51 +00:00
parent abfba1ac37
commit 8ee250d550
13 changed files with 1156 additions and 913 deletions

View File

@ -1,112 +1,127 @@
(function(context,$) {
(function (context, $) {
"use strict";
"use strict";
context.JK = context.JK || {};
context.JK.AccountAudioProfile = function(app) {
var self = this;
var logger = context.JK.logger;
var rest = context.JK.Rest();
var userId;
var user = {};
var tmpUploadPath = null;
var userDetail = null;
var avatar;
var selection = null;
var targetCropSize = 88;
var updatingAvatar = false;
context.JK = context.JK || {};
context.JK.AccountAudioProfile = function (app) {
var self = this;
var logger = context.JK.logger;
var rest = context.JK.Rest();
var userId;
var user = {};
var tmpUploadPath = null;
var userDetail = null;
var avatar;
var selection = null;
var targetCropSize = 88;
var updatingAvatar = false;
function beforeShow(data) {
userId = data.id;
function beforeShow(data) {
userId = data.id;
registerFtueSuccess();
}
registerFtueSuccess();
}
function afterShow(data) {
resetForm();
renderAudioProfileScreen()
}
function afterShow(data) {
resetForm();
renderAudioProfileScreen()
}
function beforeHide() {
unregisterFtueSuccess();
function beforeHide() {
unregisterFtueSuccess();
}
}
function renderAudioProfileScreen() {
populateAccountAudio()
}
function renderAudioProfileScreen() {
populateAccountAudio()
}
function populateAccountAudio() {
function populateAccountAudio() {
$('#account-audio-content-scroller').empty();
// load Audio Driver dropdown
var devices = context.jamClient.TrackGetDevices();
// load Audio Driver dropdown
var devices = context.jamClient.TrackGetDevices();
var options = {
devices: devices
}
var options = {
devices: devices
}
var template = context._.template($('#template-account-audio').html(), options, {variable: 'data'});
var template = context._.template($('#template-account-audio').html(), options, {variable: 'data'});
appendAudio(template);
appendAudio(template);
}
}
function appendAudio(template) {
$('#account-audio-content-scroller').html(template);
}
function appendAudio(template) {
$('#account-audio-content-scroller table tbody').replaceWith(template);
}
function resetForm() {
}
function resetForm() {
}
function handleDeleteAudioProfile(audioProfileId) {
console.log("deleting audio profile: " + audioProfileId);
function handleDeleteAudioProfile(audioProfileId) {
console.log("deleting audio profile: " + audioProfileId);
context.jamClient.TrackDeleteProfile(audioProfileId);
context.jamClient.TrackDeleteProfile(audioProfileId);
// redraw after deletion of profile
populateAccountAudio();
}
// redraw after deletion of profile
populateAccountAudio();
}
function handleStartAudioQualification() {
app.setWizardStep(1);
app.layout.showDialog('ftue');
}
function handleStartAudioQualification() {
function registerFtueSuccess() {
$('div[layout-id=ftue]').on("ftue_success", ftueSuccessHandler);
}
var useNewFtue = true;
function unregisterFtueSuccess() {
$('div[layout-id=ftue]').off("ftue_success", ftueSuccessHandler);
}
if(useNewFtue) {
app.layout.startNewFtue();
}
else {
app.setWizardStep(1);
app.layout.showDialog('ftue');
}
}
function ftueSuccessHandler() {
populateAccountAudio();
}
function registerFtueSuccess() {
$('div[layout-id=ftue]').on("ftue_success", ftueSuccessHandler);
}
// events for main screen
function events() {
// wire up main panel clicks
$('#account-audio-content-scroller').on('click', 'a[data-purpose=delete-audio-profile]', function(evt) { evt.stopPropagation(); handleDeleteAudioProfile($(this).attr('data-id')); return false; } );
$('#account-audio-content-scroller').on('click', 'a[data-purpose=add-profile]', function(evt) { evt.stopPropagation(); handleStartAudioQualification(); return false; } );
}
function unregisterFtueSuccess() {
$('div[layout-id=ftue]').off("ftue_success", ftueSuccessHandler);
}
function initialize() {
var screenBindings = {
'beforeShow': beforeShow,
'afterShow': afterShow
};
app.bindScreen('account/audio', screenBindings);
events();
}
function ftueSuccessHandler() {
populateAccountAudio();
}
this.initialize = initialize;
this.beforeShow = beforeShow;
this.afterShow = afterShow;
this.beforeHide = beforeHide;
return this;
};
// events for main screen
function events() {
// wire up main panel clicks
$('#account-audio-content-scroller').on('click', 'a[data-purpose=delete-audio-profile]', function (evt) {
evt.stopPropagation();
handleDeleteAudioProfile($(this).attr('data-id'));
return false;
});
$('#account-audio-content-scroller').on('click', 'a[data-purpose=add-profile]', function (evt) {
evt.stopPropagation();
handleStartAudioQualification();
return false;
});
}
})(window,jQuery);
function initialize() {
var screenBindings = {
'beforeShow': beforeShow,
'afterShow': afterShow
};
app.bindScreen('account/audio', screenBindings);
events();
}
this.initialize = initialize;
this.beforeShow = beforeShow;
this.afterShow = afterShow;
this.beforeHide = beforeHide;
return this;
};
})(window, jQuery);

View File

@ -119,7 +119,7 @@
// If user hasn't completed FTUE - do so now.
if (!(context.jamClient.FTUEGetStatus())) {
app.afterFtue = function() { submitForm(evt); };
app.layout.showDialog('ftue');
app.layout.startNewFtue();
return;
}

View File

@ -18,6 +18,9 @@
var jamClient = context.jamClient;
var win32 = true;
// tracks in the loopback FTUe what the currently chosen audio driver is
var currentAudioDriverId = null;
var deviceSetMap = {
'audio-input': jamClient.FTUESetMusicInput,
'audio-output': jamClient.FTUESetMusicOutput,
@ -32,6 +35,14 @@
'ftue-audio-output-fader': jamClient.FTUESetOutputVolume
};
var faderReadMap = {
'ftue-2-audio-input-fader': jamClient.FTUEGetInputVolume,
'ftue-2-voice-input-fader': jamClient.FTUEGetOutputVolume,
'ftue-audio-input-fader': jamClient.FTUEGetInputVolume,
'ftue-voice-input-fader': jamClient.FTUEGetChatInputVolume,
'ftue-audio-output-fader': jamClient.FTUEGetOutputVolume
};
function latencyTimeoutCheck() {
if (context.JK.FtueWizard.latencyTimeout) {
jamClient.FTUERegisterLatencyCallback('');
@ -72,6 +83,20 @@
}
function afterShow(data) {
}
// renders volumes based on what the backend says
function renderVolumes() {
$.each(context._.keys(faderReadMap), function (index, faderId) {
// faderChange takes a value from 0-100
var $fader = $('[fader-id="' + faderId + '"]');
var db = faderReadMap[faderId]();
var faderPct = db + 80;
context.JK.FaderHelpers.setHandlePosition($fader, faderPct);
//faderChange(faderId, faderPct);
});
}
function faderChange(faderId, newValue, dragging) {
@ -81,15 +106,67 @@
setFunction(mixerLevel);
}
function setSaveButtonState($save, enabled) {
if (enabled) {
$save.removeClass('disabled');
}
else {
$save.addClass('disabled');
}
}
function checkValidStateForTesting() {
var reqMissing = !musicInAndOutSet() || currentAudioDriverId == null || currentAudioDriverId == '';
if(reqMissing ) {
renderDisableTest();
}
else {
renderEnableTest();
}
}
function renderDisableTest() {
$('#btn-ftue-test').addClass('disabled');
}
function renderEnableTest() {
$('#btn-ftue-test').removeClass('disabled');
}
function renderStartNewFtueLatencyTesting() {
setSaveButtonState($('#btn-ftue-2-save'), false);
$('#ftue-2-spinner').show().css('display', 'inline-block');
}
function renderStopNewFtueLatencyTesting() {
$('#ftue-2-spinner').hide();
}
function settingsInit() {
jamClient.FTUEInit();
setLevels(0);
//setLevels(0);
resetFtueLatencyView();
setSaveButtonState($('#btn-ftue-2-save'), false);
if (jamClient.GetOSAsString() !== "Win32") {
$('#btn-ftue-2-asio-control-panel').hide();
}
renderDisableTest();
// Always reset the driver select box to "Choose..." which forces everything
// to sync properly when the user reselects their driver of choice.
// VRFS-375 and VRFS-561
$('[layout-wizard="ftue"] [layout-wizard-step="0"] .settings-2-device select').val("");
$('[layout-wizard="ftue"] [layout-wizard-step="0"] .settings-2-voice select').val("");
$('[layout-wizard="ftue"] [layout-wizard-step="0"] #ftue-2-asio-framesize').val("").easyDropDown('disable');
$('[layout-wizard="ftue"] [layout-wizard-step="0"] #ftue-2-asio-input-latency').val("0").easyDropDown('disable');
$('[layout-wizard="ftue"] [layout-wizard-step="0"] #ftue-2-asio-output-latency').val("0").easyDropDown('disable');
// with the old ftue, this is pretty annoying to reset these everytime
$('[layout-wizard="ftue"] [layout-wizard-step="2"] .asio-settings .settings-driver select').val("");
$('[layout-wizard="ftue"] [layout-wizard-step="2"] .settings-controls select[data-device="audio-input"]').val("");
$('[layout-wizard="ftue"] [layout-wizard-step="2"] .settings-controls select[data-device="audio-output"]').val("");
$('[layout-wizard="ftue"] [layout-wizard-step="2"] .settings-controls select[data-device="voice-chat-output"]').val("");
}
function setLevels(db) {
@ -251,6 +328,8 @@
});
if (musicInAndOutSet()) {
renderVolumes();
// If there is no voice-chat-input selected, let the back-end know
// that we're using music for voice-chat.
if ($('[layout-wizard-step="2"] select[data-device="voice-chat-input"]').val()) {
@ -265,7 +344,7 @@
logger.debug("Calling FTUESave(" + persist + ")");
var response = jamClient.FTUESave(persist);
setLevels(0);
//setLevels(0);
if (response) {
logger.warn(response);
// TODO - we may need to do something about errors on save.
@ -307,6 +386,15 @@
ftueSave(false);
}
function testRequested(evt) {
evt.preventDefault();
var $testButton = $('#btn-ftue-test');
if (!$testButton.hasClass('disabled')) {
app.setWizardStep(3);
}
return false;
}
function videoLinkClicked(evt) {
var myOS = jamClient.GetOSAsString();
var link;
@ -337,6 +425,8 @@
$('#asio-framesize').on('change', setAsioFrameSize);
$('#asio-input-latency').on('change', setAsioInputLatency);
$('#asio-output-latency').on('change', setAsioOutputLatency);
$('#btn-ftue-test').on('click', testRequested)
// New FTUE events
$('.ftue-new .settings-2-device select').on('change', newFtueAudioDeviceChanged);
$('.ftue-new .settings-2-voice select').on('change', newFtueAudioDeviceChanged);
@ -457,6 +547,8 @@
jamClient.FTUESave(true);
jamClient.FTUESetStatus(true); // No FTUE wizard next time
rest.userCertifiedGear({success: true});
// notify anyone curious about how it went
$('div[layout-id=ftue]').trigger('ftue_success');
app.layout.closeDialog('ftue');
if (app.afterFtue) {
// If there's a function to invoke, invoke it.
@ -472,6 +564,7 @@
// We also call jamClient.FTUEGetExpectedLatency, which returns a structure like:
// { latency: 11.1875, latencyknown: true, latencyvar: 1}
function newFtueAudioDeviceChanged(evt) {
renderStartNewFtueLatencyTesting();
var $select = $(evt.currentTarget);
var $audioSelect = $('.ftue-new .settings-2-device select');
@ -486,6 +579,7 @@
jamClient.TrackSetChatEnable(false);
}
if (!audioDriverId) {
renderStopNewFtueLatencyTesting();
// reset back to 'Choose...'
newFtueEnableControls(false);
return;
@ -516,13 +610,25 @@
// TODO FIXME - how to handle a driver selection where we are unable to
// autoset both inputs and outputs? (I'd think this could happen if either
// the input or output side returned no values)
renderStopNewFtueLatencyTesting();
return;
}
newFtueEnableControls(true);
newFtueOsSpecificSettings();
setLevels(0);
// make sure whatever the user sees in the frontend is what the backend thinks
// this is necesasry because if you do a FTUE pass, close the client, and pick the same device
// the backend will *silently* use values from before, because the frontend does not query the backend
// for these values anywhere.
newFtueAsioFrameSizeToBackend($('#ftue-2-asio-framesize'));
newFtueAsioInputLatencyToBackend($('#ftue-2-asio-input-latency'));
newFtueAsioOutputLatencyToBackend($('#ftue-2-asio-output-latency'));
//setLevels(0);
renderVolumes();
newFtueUpdateLatencyView('loading');
jamClient.FTUESave(false);
setVuCallbacks();
@ -545,33 +651,67 @@
newFtueSave(false);
}
function newFtueSetAsioFrameSize(evt) {
var val = parseFloat($(evt.currentTarget).val(), 10);
// simply tells backend what frontend shows in the UI
function newFtueAsioFrameSizeToBackend($input) {
var val = parseFloat($input.val(), 10);
if (isNaN(val)) {
return;
logger.warn("unable to get value from framesize input: %o", $input.val());
return false;
}
logger.debug("Calling FTUESetFrameSize(" + val + ")");
jamClient.FTUESetFrameSize(val);
return true;
}
function newFtueAsioInputLatencyToBackend($input) {
var val = parseInt($input.val(), 10);
if (isNaN(val)) {
logger.warn("unable to get value from input latency input: %o", $input.val());
return false;
}
logger.debug("Calling FTUESetInputLatency(" + val + ")");
jamClient.FTUESetInputLatency(val);
return true;
}
function newFtueAsioOutputLatencyToBackend($input) {
var val = parseInt($input.val(), 10);
if (isNaN(val)) {
logger.warn("unable to get value from output latency input: %o", $input.val());
return false;
}
logger.debug("Calling FTUESetOutputLatency(" + val + ")");
jamClient.FTUESetOutputLatency(val);
return true;
}
function newFtueSetAsioFrameSize(evt) {
renderStartNewFtueLatencyTesting();
if(!newFtueAsioFrameSizeToBackend($(evt.currentTarget))) {
renderStopNewFtueLatencyTesting();
return;
}
newFtueSave(false);
}
function newFtueSetAsioInputLatency(evt) {
var val = parseInt($(evt.currentTarget).val(), 10);
if (isNaN(val)) {
renderStartNewFtueLatencyTesting();
if(!newFtueAsioInputLatencyToBackend($(evt.currentTarget))) {
renderStopNewFtueLatencyTesting();
return;
}
logger.debug("Calling FTUESetInputLatency(" + val + ")");
jamClient.FTUESetInputLatency(val);
newFtueSave(false);
}
function newFtueSetAsioOutputLatency(evt) {
var val = parseInt($(evt.currentTarget).val(), 10);
if (isNaN(val)) {
renderStartNewFtueLatencyTesting();
if(!newFtueAsioOutputLatencyToBackend($(evt.currentTarget))) {
renderStopNewFtueLatencyTesting();
return;
}
logger.debug("Calling FTUESetOutputLatency(" + val + ")");
jamClient.FTUESetOutputLatency(val);
newFtueSave(false);
}
@ -626,6 +766,27 @@
}
function resetFtueLatencyView() {
var $report = $('.ftue-new .latency .report');
var $instructions = $('.ftue-new .latency .instructions');
$('.ms-label', $report).empty();
$('p', $report).empty();
var latencyClass = 'start';
$report.removeClass('good acceptable bad');
$report.addClass(latencyClass);
var instructionClasses = ['neutral', 'good', 'acceptable', 'bad', 'start', 'loading'];
$.each(instructionClasses, function (idx, val) {
$('p.' + val, $instructions).hide();
});
$('p.' + latencyClass, $instructions).show();
}
// Given a latency structure, update the view.
function newFtueUpdateLatencyView(latency) {
var $report = $('.ftue-new .latency .report');
@ -639,26 +800,26 @@
latencyValue = Math.round(latencyValue * 100) / 100;
if (latency.latency <= 10) {
latencyClass = "good";
$saveButton.removeClass('disabled');
setSaveButtonState($saveButton, true);
} else if (latency.latency <= 20) {
latencyClass = "acceptable";
$saveButton.removeClass('disabled');
setSaveButtonState($saveButton, true);
} else {
latencyClass = "bad";
$saveButton.addClass('disabled');
setSaveButtonState($saveButton, false);
}
} else {
latencyClass = "unknown";
$saveButton.addClass('disabled');
setSaveButtonState($saveButton, false);
}
$('.ms-label', $report).html(latencyValue);
$('p', $report).html('milliseconds');
$report.removeClass('good acceptable bad');
$report.removeClass('good acceptable bad unknown');
$report.addClass(latencyClass);
var instructionClasses = ['neutral', 'good', 'acceptable', 'bad', 'start', 'loading'];
var instructionClasses = ['neutral', 'good', 'acceptable', 'unknown', 'bad', 'start', 'loading'];
$.each(instructionClasses, function (idx, val) {
$('p.' + val, $instructions).hide();
});
@ -666,15 +827,17 @@
$('p.loading', $instructions).show();
} else {
$('p.' + latencyClass, $instructions).show();
renderStopNewFtueLatencyTesting();
}
}
function audioDriverChanged(evt) {
var $select = $(evt.currentTarget);
var driverId = $select.val();
jamClient.FTUESetMusicDevice(driverId);
currentAudioDriverId = $select.val();
jamClient.FTUESetMusicDevice(currentAudioDriverId);
loadAudioDevices();
setAsioSettingsVisibility();
checkValidStateForTesting();
}
function audioDeviceChanged(evt) {
@ -684,6 +847,7 @@
ftueSave(false);
setVuCallbacks();
}
checkValidStateForTesting();
}
function setAudioDevice($select) {

File diff suppressed because it is too large Load Diff

View File

@ -143,7 +143,7 @@
// If no FTUE, show that first.
if (!(context.jamClient.FTUEGetStatus())) {
app.afterFtue = function() { joinClick(session.id); };
app.layout.showDialog('ftue');
app.layout.startNewFtue();
return;
} else {
joinClick(session.id);

View File

@ -151,6 +151,19 @@
margin-right:0;
}
.account-audio {
table.generaltable td {
vertical-align:middle;
}
.button-orange, .button-grey {
margin-bottom:9px;
}
}
.button-grey {
margin-right:6px;
}

View File

@ -42,8 +42,9 @@ div.dialog.ftue .ftue-inner div[layout-wizard-step="3"] {
}
}
div.dialog.ftue .ftue-inner div[layout-wizard-step="0"] {
}
#ftue-latency-needle {
position:absolute;
width: 6px;
@ -188,6 +189,7 @@ div.dialog.ftue {
}
.instructions p.bad {
margin-top: -6px;
line-height: 16px;
}
.instructions p a {
font-weight: bold;
@ -383,6 +385,13 @@ div.dialog.ftue {
color: darken(#fff, 5);
text-decoration: none;
}
.spinner-small {
display:none;
margin-top: 3px;
position: relative;
top: 12px;
}
}
}

View File

@ -476,6 +476,16 @@ input[type="text"], input[type="password"]{
height:128px;
}
.spinner-small {
background-image: url('/assets/shared/spinner.gif');
background-repeat:no-repeat;
background-position:center;
width:32px;
height:32px;
background-size: 50% 50%;
}
// disable text selection for the in-session panel, ftue, and arbitrary elements marked with .no-selection-range
div[layout-id=session], div[layout-id=ftue], .no-selection-range {
-webkit-touch-callout: none;

View File

@ -201,6 +201,14 @@ small, .small {font-size:11px;}
cursor:pointer;
color:#FC9;
text-decoration:none;
&.disabled {
@extend .button-grey;
}
&.disabled:hover {
@extend .button-grey:hover;
}
}
.smallbutton {

View File

@ -57,6 +57,7 @@ body.jam {
right: 0;
bottom: 0;
height: 50px;
z-index:-1;
box-shadow: inset 0 -50px 30px -35px #fff;
}

View File

@ -15,26 +15,35 @@
<!-- profile scrolling area -->
<div class="content-body">
<div id="account-audio-content-scroller" class="content-body-scroller account-content-scroller">
<!-- content wrapper -->
<div class="content-wrapper account-audio">
<br />
<div class="account-left">
<h2>audio profiles:</h2>
</div>
<table class="generaltable audioprofile f14" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th align="left">NAME</th>
<th class="noborder actions">DELETE</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<br clear="all" />
<div class="left"><a href="#" data-purpose="add-profile" class="button-orange">ADD NEW PROFILE</a></div><div class="right"><a href="javascript:history.go(-1)" class="button-grey">BACK</a></div>
</div>
</div>
</div>
<!-- end content scrolling area -->
</div>
<script type="text/template" id="template-account-audio">
<!-- content wrapper -->
<div class="content-wrapper account-audio">
<br />
<div class="account-left">
<h2>audio profiles:</h2>
</div>
<table class="generaltable audioprofile f14" cellpadding="0" cellspacing="0">
<tr>
<th align="left">NAME</th>
<th class="noborder actions">DELETE</th>
</tr>
<tbody>
{% var keys = Object.keys(data.devices); %}
{% for (var i = 0; i < keys.length; i++) { %}
<tr>
@ -42,12 +51,8 @@
<td class="actions"><a href="#" data-id="{{keys[i]}}" data-purpose="delete-audio-profile" class="button-orange">DELETE</a></td>
</tr>
{% } %}
</table>
<br clear="all" />
<div class="left"><a href="#" data-purpose="add-profile" class="button-orange">ADD NEW PROFILE</a></div><div class="right"><a href="javascript:history.go(-1)" class="button-grey">BACK</a></div>
</div>
<!-- end content wrapper -->
</tbody>
</script>

View File

@ -43,7 +43,7 @@
<%= image_tag "content/icon_resync.png", {:width => 12, :height => 14} %>
RESYNC
</a>
<a class="button-grey" id="btn-ftue-2-asio-control-panel">ASIO SETTINGS</a>
<a class="button-grey" id="btn-ftue-2-asio-control-panel" os="win32">ASIO SETTINGS</a>
</div>
<div class="subcolumn first">
Frame<br />
@ -113,15 +113,16 @@
<p class="neutral loading" style="display:none;">Estimating latency...</p>
<p class="good" style="display:none;">Your audio speed is good. When done with settings, click Save Settings to continue.</p>
<p class="acceptable" style="display:none;">Your audio speed is acceptable, but borderline. Try setting Frame to 2.5 and Buffers to 0 and see if your audio quality is still OK. When done with settings, click Save Settings to continue. You can also view the <a href="#">Choosing an Audio Device</a> article for information on faster audio devices.</p>
<p class="bad" style="display:none;">We're sorry, but your audio speed is too slow to use JamKazam. Try setting Frame to 2.5 and Buffers to 0 and see if your audio quality is still OK. You can also view the <a href="#">Choosing an Audio Device</a> article for information on faster audio devices.</p>
<p class="bad" style="display:none;">We're sorry, but your audio speed is too slow to use JamKazam. Try setting Frame to 2.5 and Buffers to 0 and see if your audio quality is still OK. You can also view the <a href="#">Choosing an Audio Device</a> article for information on faster audio devices. You can also click <a href="#" layout-wizard-link="2">here</a> to try another test which may be able to measure your audio performance more accurately.</p>
</div>
</div>
</div>
<div class="right mr30 buttonbar">
<span class="spinner-small" id="ftue-2-spinner"></span>
<a class="button-grey" layout-action="close">CANCEL</a>
<a class="button-grey">HELP</a>&nbsp;
<a class="button-orange" id="btn-ftue-2-save">SAVE SETTINGS</a>
<a class="button-orange disabled" id="btn-ftue-2-save">SAVE SETTINGS</a>
</div>
</div>
@ -242,7 +243,7 @@
</div>
</div>
<div class="section settings-controls">
<div class="section settings-controls">
<div class="section audio-input">
<div class="right">
<%= image_tag "shared/icon_help.png", {:width => 12, :height => 12} %>
@ -293,7 +294,7 @@
<div class="right mr30 buttonbar">
<a class="button-grey" layout-wizard-link="1">BACK</a>
<a class="button-grey">HELP</a>&nbsp;
<a class="button-orange" layout-wizard-link="3">NEXT</a>
<a class="button-orange disabled" id="btn-ftue-test">NEXT</a>
</div>
</div>

View File

@ -159,7 +159,7 @@
right: 0;
bottom: 0;
height: 50px;
box-shadow: inset 0 -50px 30px -35px #fff;
}