mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Merge pull request #574 from juliandescottes/warning-notifications
Warning notifications
This commit is contained in:
commit
156161f7c8
64
misc/icons/source/common-warning-red.svg
Normal file
64
misc/icons/source/common-warning-red.svg
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="42"
|
||||
height="42"
|
||||
viewBox="0 0 41.999999 41.999999"
|
||||
enable-background="new 0 0 99.997 69.373"
|
||||
xml:space="preserve"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="common-warning-red.svg"
|
||||
inkscape:export-filename="C:\Development\git\piskel\misc\icons\source\tool-move.png"
|
||||
inkscape:export-xdpi="45"
|
||||
inkscape:export-ydpi="45"><metadata
|
||||
id="metadata9"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs7" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1148"
|
||||
id="namedview5"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="85.612634"
|
||||
inkscape:cy="3.0742543"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
|
||||
<path
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
d="m 21,4.2499995 c -0.868171,0 -1.517453,0.2705716 -2,1.03125 L 3.9999999,34.999999 c -0.6703157,1.211185 0.6156981,2.999959 2,3 l 29.9999991,0 c 1.377219,0.0098 2.645421,-1.78334 2,-3 l -15,-29.6874995 C 22.632848,4.6114627 21.868171,4.2499995 21,4.2499995 z m 0,6.2187495 11.999999,23.53125 -23.9999992,0 z"
|
||||
id="rect3765"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zcccccczcccc" /><path
|
||||
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
d="m 20.572432,16.003047 c -0.858253,0.109012 -1.577503,1.040604 -1.572402,2.036618 L 20,25.963381 c 9.2e-5,1.066342 -0.158856,2.036512 0.765534,2.036618 l 0.468961,0 c 0.92439,-1.06e-4 0.765412,-0.970276 0.765504,-2.036618 l 1,-7.923716 c -9.2e-5,-1.066342 -0.841114,-2.036512 -1.765504,-2.036618 l -0.468961,0 c -0.0643,-0.0041 -0.128799,-0.0041 -0.193102,0 z"
|
||||
id="rect3772"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccc" /><path
|
||||
style="fill:#ff0000;fill-opacity:1;stroke:#00ffff;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:1.60000000000000010"
|
||||
d="m 20.999298,29.000086 c 0.620953,-0.006 0.971639,0.298697 0.999273,1.499911 0.02763,1.201212 -0.347092,1.493936 -0.999273,1.499909 -0.65218,0.006 -1.002864,-0.275261 -0.999271,-1.499909 0.0036,-1.22465 0.378318,-1.493938 0.999271,-1.499911 z"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zzzzz" /></svg>
|
After Width: | Height: | Size: 4.1 KiB |
@ -1,3 +1,9 @@
|
||||
@keyframes fade {
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
@keyframes glow {
|
||||
0% { opacity: 0.66; }
|
||||
50% { opacity: 1; }
|
||||
100% { opacity: 0.66; }
|
||||
}
|
||||
|
66
src/css/dialogs-performance-info.css
Normal file
66
src/css/dialogs-performance-info.css
Normal file
@ -0,0 +1,66 @@
|
||||
.performance-link {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
z-index: 11000;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition : opacity 0.3s;
|
||||
}
|
||||
|
||||
.performance-link.visible {
|
||||
display: block;
|
||||
opacity: 0.66;
|
||||
animation: glow 2s infinite;
|
||||
}
|
||||
|
||||
.performance-link.visible:hover {
|
||||
opacity: 1;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
#dialog-container.performance-info {
|
||||
width: 500px;
|
||||
height: 525px;
|
||||
top : 50%;
|
||||
left : 50%;
|
||||
position : absolute;
|
||||
margin-left: -250px;
|
||||
}
|
||||
|
||||
.dialog-performance-info-body {
|
||||
font-size: 13px;
|
||||
letter-spacing: 1px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.dialog-performance-info-body ul {
|
||||
border: 1px solid #666;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.dialog-performance-info-body li {
|
||||
list-style-type: initial;
|
||||
margin: 0 20px;
|
||||
}
|
||||
|
||||
.dialog-performance-info-body sup {
|
||||
color: gold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.show #dialog-container.performance-info {
|
||||
margin-top: -300px;
|
||||
}
|
||||
|
||||
.dialog-performance-info-body .warning-icon {
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.dialog-performance-info-body .warning-icon-info {
|
||||
overflow: hidden;
|
||||
margin-left: 30px;
|
||||
}
|
BIN
src/img/icons/common/common-warning-red.png
Normal file
BIN
src/img/icons/common/common-warning-red.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 446 B |
BIN
src/img/icons/common/common-warning-red@2x.png
Normal file
BIN
src/img/icons/common/common-warning-red@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 851 B |
@ -71,13 +71,17 @@
|
||||
@@include('templates/misc-templates.html', {})
|
||||
@@include('templates/popup-preview.html', {})
|
||||
|
||||
<span class="cheatsheet-link icon-common-keyboard-gold" rel="tooltip" data-placement="right" title="Keyboard shortcuts"> </span>
|
||||
<span class="cheatsheet-link icon-common-keyboard-gold"
|
||||
rel="tooltip" data-placement="right" title="Keyboard shortcuts"> </span>
|
||||
<div class="performance-link icon-common-warning-red"
|
||||
rel="tooltip" data-placement="left" title="Performance problem detected, learn more."> </div>
|
||||
|
||||
<!-- dialogs partials -->
|
||||
@@include('templates/dialogs/create-palette.html', {})
|
||||
@@include('templates/dialogs/import-image.html', {})
|
||||
@@include('templates/dialogs/browse-local.html', {})
|
||||
@@include('templates/dialogs/cheatsheet.html', {})
|
||||
@@include('templates/dialogs/performance-info.html', {})
|
||||
|
||||
<!-- settings-panel partials -->
|
||||
@@include('templates/settings/application.html', {})
|
||||
|
@ -80,6 +80,8 @@ var Events = {
|
||||
|
||||
CURRENT_COLORS_UPDATED : 'CURRENT_COLORS_UPDATED',
|
||||
|
||||
PERFORMANCE_REPORT_CHANGED : 'PERFORMANCE_REPORT_CHANGED',
|
||||
|
||||
// Tests
|
||||
MOUSE_EVENT : 'MOUSE_EVENT',
|
||||
KEYBOARD_EVENT : 'KEYBOARD_EVENT',
|
||||
|
@ -153,6 +153,13 @@
|
||||
document.querySelector('#drawing-canvas-container'));
|
||||
this.fileDropperService.init();
|
||||
|
||||
this.userWarningController = new pskl.controller.UserWarningController(this.piskelController);
|
||||
this.userWarningController.init();
|
||||
|
||||
this.performanceReportService = new pskl.service.performance.PerformanceReportService(
|
||||
this.piskelController, this.currentColorsService);
|
||||
this.performanceReportService.init();
|
||||
|
||||
this.drawingLoop = new pskl.rendering.DrawingLoop();
|
||||
this.drawingLoop.addCallback(this.render, this);
|
||||
this.drawingLoop.start();
|
||||
|
55
src/js/controller/UserWarningController.js
Normal file
55
src/js/controller/UserWarningController.js
Normal file
@ -0,0 +1,55 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller');
|
||||
|
||||
ns.UserWarningController = function (piskelController, currentColorsService) {
|
||||
this.piskelController = piskelController;
|
||||
this.currentColorsService = currentColorsService;
|
||||
};
|
||||
|
||||
// This method is not attached to the prototype because we want to trigger it
|
||||
// from markup generated for a notification message.
|
||||
ns.UserWarningController.showPerformanceInfoDialog = function () {
|
||||
$.publish(Events.DIALOG_DISPLAY, {
|
||||
dialogId: 'performance-info'
|
||||
});
|
||||
};
|
||||
|
||||
ns.UserWarningController.prototype.init = function () {
|
||||
$.subscribe(Events.PERFORMANCE_REPORT_CHANGED, this.onPerformanceReportChanged_.bind(this));
|
||||
|
||||
this.performanceLinkEl = document.querySelector('.performance-link');
|
||||
pskl.utils.Event.addEventListener(
|
||||
this.performanceLinkEl,
|
||||
'click',
|
||||
ns.UserWarningController.showPerformanceInfoDialog,
|
||||
this
|
||||
);
|
||||
};
|
||||
|
||||
ns.UserWarningController.prototype.destroy = function () {
|
||||
pskl.utils.Event.removeAllEventListeners(this);
|
||||
this.performanceLinkEl = null;
|
||||
};
|
||||
|
||||
ns.UserWarningController.prototype.onPerformanceReportChanged_ = function (event, report) {
|
||||
var shouldDisplayWarning = report.hasProblem();
|
||||
|
||||
// Check if a performance warning is already displayed.
|
||||
var isWarningDisplayed = this.performanceLinkEl.classList.contains('visible');
|
||||
|
||||
// Show/hide the performance warning link depending on the received report.
|
||||
this.performanceLinkEl.classList.toggle('visible', shouldDisplayWarning);
|
||||
|
||||
// Show a notification message if the new report indicates a performance issue
|
||||
// and we were not displaying a warning before.
|
||||
if (shouldDisplayWarning && !isWarningDisplayed) {
|
||||
$.publish(Events.SHOW_NOTIFICATION, [{
|
||||
'content': 'Performance problem detected, ' +
|
||||
'<a href="#" style="color:red;"' +
|
||||
'onclick="pskl.controller.UserWarningController.showPerformanceInfoDialog()">' +
|
||||
'learn more?</a>',
|
||||
'hideDelay' : 5000
|
||||
}]);
|
||||
}
|
||||
};
|
||||
})();
|
@ -17,6 +17,10 @@
|
||||
'import-image' : {
|
||||
template : 'templates/dialogs/import-image.html',
|
||||
controller : ns.ImportImageController
|
||||
},
|
||||
'performance-info' : {
|
||||
template : 'templates/dialogs/performance-info.html',
|
||||
controller : ns.PerformanceInfoController
|
||||
}
|
||||
};
|
||||
|
||||
|
11
src/js/controller/dialogs/PerformanceInfoController.js
Normal file
11
src/js/controller/dialogs/PerformanceInfoController.js
Normal file
@ -0,0 +1,11 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller.dialogs');
|
||||
|
||||
ns.PerformanceInfoController = function () {};
|
||||
|
||||
pskl.utils.inherit(ns.PerformanceInfoController, ns.AbstractDialogController);
|
||||
|
||||
ns.PerformanceInfoController.prototype.init = function () {
|
||||
this.superclass.init.call(this);
|
||||
};
|
||||
})();
|
45
src/js/service/performance/PerformanceReport.js
Normal file
45
src/js/service/performance/PerformanceReport.js
Normal file
@ -0,0 +1,45 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.service.performance');
|
||||
|
||||
/**
|
||||
* We consider that piskel should behave correctly for a sprite with the following specs:
|
||||
* - 256*256
|
||||
* - 30 frames
|
||||
* - 5 layers
|
||||
* - 30 colors
|
||||
* Based on these assumptions, as well as a few arbitrary hard limits we try to check
|
||||
* if the provided sprite might present a performance issue.
|
||||
*
|
||||
* @param {Piskel} piskel the sprite to analyze
|
||||
* @param {Number} colorsCount number of colors for the current sprite
|
||||
* (not part of the piskel model so has to be provided separately).
|
||||
*/
|
||||
ns.PerformanceReport = function (piskel, colorsCount) {
|
||||
var pixels = piskel.getWidth() * piskel.getHeight();
|
||||
this.resolution = pixels > (500 * 500);
|
||||
|
||||
var layersCount = piskel.getLayers().length;
|
||||
this.layers = layersCount > 25;
|
||||
|
||||
var framesCount = piskel.getLayerAt(0).size();
|
||||
this.frames = framesCount > 100;
|
||||
|
||||
this.colors = colorsCount > 100;
|
||||
|
||||
var overallScore = (pixels / 2500) + (layersCount * 4) + framesCount + colorsCount;
|
||||
this.overall = overallScore > 100;
|
||||
};
|
||||
|
||||
ns.PerformanceReport.prototype.equals = function (report) {
|
||||
return (report instanceof ns.PerformanceReport &&
|
||||
this.resolution == report.resolution &&
|
||||
this.layers == report.layers &&
|
||||
this.frames == report.frames &&
|
||||
this.colors == report.colors &&
|
||||
this.overall == report.overall);
|
||||
};
|
||||
|
||||
ns.PerformanceReport.prototype.hasProblem = function () {
|
||||
return this.resolution || this.layers || this.frames || this.colors || this.overall;
|
||||
};
|
||||
})();
|
25
src/js/service/performance/PerformanceReportService.js
Normal file
25
src/js/service/performance/PerformanceReportService.js
Normal file
@ -0,0 +1,25 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.service.performance');
|
||||
|
||||
ns.PerformanceReportService = function (piskelController, currentColorsService) {
|
||||
this.piskelController = piskelController;
|
||||
this.currentColorsService = currentColorsService;
|
||||
|
||||
this.currentReport = null;
|
||||
};
|
||||
|
||||
ns.PerformanceReportService.prototype.init = function () {
|
||||
$.subscribe(Events.HISTORY_STATE_SAVED, this.createReport_.bind(this));
|
||||
};
|
||||
|
||||
ns.PerformanceReportService.prototype.createReport_ = function () {
|
||||
var report = new ns.PerformanceReport(
|
||||
this.piskelController.getPiskel(),
|
||||
this.currentColorsService.getCurrentColors().length);
|
||||
|
||||
if (!report.equals(this.currentReport)) {
|
||||
$.publish(Events.PERFORMANCE_REPORT_CHANGED, [report]);
|
||||
this.currentReport = report;
|
||||
}
|
||||
};
|
||||
})();
|
@ -115,6 +115,7 @@
|
||||
"js/controller/NotificationController.js",
|
||||
"js/controller/TransformationsController.js",
|
||||
"js/controller/CanvasBackgroundController.js",
|
||||
"js/controller/UserWarningController.js",
|
||||
|
||||
// Settings sub-controllers
|
||||
"js/controller/settings/AbstractSettingController.js",
|
||||
@ -139,6 +140,7 @@
|
||||
"js/controller/dialogs/ImportImageController.js",
|
||||
"js/controller/dialogs/BrowseLocalController.js",
|
||||
"js/controller/dialogs/CheatsheetController.js",
|
||||
"js/controller/dialogs/PerformanceInfoController.js",
|
||||
|
||||
// Dialogs controller
|
||||
"js/controller/dialogs/DialogsController.js",
|
||||
@ -181,6 +183,8 @@
|
||||
"js/service/FileDropperService.js",
|
||||
"js/service/SelectedColorsService.js",
|
||||
"js/service/MouseStateService.js",
|
||||
"js/service/performance/PerformanceReport.js",
|
||||
"js/service/performance/PerformanceReportService.js",
|
||||
"js/service/storage/LocalStorageService.js",
|
||||
"js/service/storage/GalleryStorageService.js",
|
||||
"js/service/storage/DesktopStorageService.js",
|
||||
|
@ -22,6 +22,7 @@
|
||||
"css/dialogs-cheatsheet.css",
|
||||
"css/dialogs-create-palette.css",
|
||||
"css/dialogs-import-image.css",
|
||||
"css/dialogs-performance-info.css",
|
||||
"css/notifications.css",
|
||||
"css/toolbox.css",
|
||||
"css/toolbox-layers-list.css",
|
||||
|
32
src/templates/dialogs/performance-info.html
Normal file
32
src/templates/dialogs/performance-info.html
Normal file
@ -0,0 +1,32 @@
|
||||
<script type="text/template" id="templates/dialogs/performance-info.html">
|
||||
<div class="dialog-wrapper">
|
||||
<h3 class="dialog-head">
|
||||
Performance issues
|
||||
<span class="dialog-close">X</span>
|
||||
</h3>
|
||||
<div class="dialog-performance-info-body">
|
||||
<p>The current sprite may exceed the recommendations for Piskel.</p>
|
||||
<p>You can ignore this warning and continue working with your sprite but you might experience the following issues:</p>
|
||||
<ul>
|
||||
<li>saving failures</li>
|
||||
<li>slowdowns</li>
|
||||
<li>crashes</li>
|
||||
</ul>
|
||||
<p>If you ignore this warning, please save often!</p>
|
||||
<p>To fix the issue, try adjusting your sprite settings:</p>
|
||||
<ul>
|
||||
<li>sprite resolution <sup title="recommended: lower than 256x256, max: 512x512" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>number of layers <sup title="recommended: lower than 5, max: 20" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>number of frames <sup title="recommended: lower than 25, max: 100" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>number of colors <sup title="max: 100" rel="tooltip" data-placement="top">?</sup></li>
|
||||
</ul>
|
||||
<p>We strive to improve Piskel, its performances and stability, but this is a personal project with limited time and resources.
|
||||
We prefer to warn you early rather than having you lose your work.</p>
|
||||
<p>Feedback welcome at <a href="https://github.com/juliandescottes/piskel" target="_blank">https://github.com/juliandescottes/piskel</a></p>
|
||||
<p>
|
||||
<div class="warning-icon icon-common-warning-red"> </div>
|
||||
<div class="warning-icon-info">This icon will remain on the top-bottom of the application until the performance issue is fixed. You can click on it at anytime to display this information again.</div>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user