mirror of
https://github.com/sudoxnym/habitica.git
synced 2026-07-31 23:11:15 +00:00
rewrite: notifications!! also, surpressing _.extend user for now. need to fix ASAP!
This commit is contained in:
parent
42f4e6f69c
commit
13a4aadfb4
5 changed files with 120 additions and 119 deletions
|
|
@ -14,7 +14,6 @@ loadJavaScripts = (model) ->
|
|||
###
|
||||
Internal Scripts
|
||||
###
|
||||
require "../vendor/jquery-ui-1.10.2/jquery-1.9.1.js"
|
||||
require "../vendor/jquery.cookie.min.js"
|
||||
require "../vendor/bootstrap/js/bootstrap.min.js"
|
||||
require "../vendor/jquery.bootstrap-growl.min.js"
|
||||
|
|
@ -22,47 +21,14 @@ loadJavaScripts = (model) ->
|
|||
require "../vendor/bootstrap-tour/bootstrap-tour"
|
||||
|
||||
unless (model.get('_mobileDevice') is true)
|
||||
require "../vendor/jquery-ui-1.10.2/ui/jquery.ui.core.js"
|
||||
require "../vendor/jquery-ui-1.10.2/ui/jquery.ui.widget.js"
|
||||
require "../vendor/jquery-ui-1.10.2/ui/jquery.ui.mouse.js"
|
||||
require "../vendor/jquery-ui-1.10.2/ui/jquery.ui.sortable.js"
|
||||
require "../vendor/sticky"
|
||||
|
||||
# note: external script loading is handled in app.on('render') near the bottom of this file (see https://groups.google.com/forum/?fromgroups=#!topic/derbyjs/x8FwdTLEuXo)
|
||||
|
||||
###
|
||||
Setup jQuery UI Sortable
|
||||
###
|
||||
setupSortable = (model) ->
|
||||
unless (model.get('_mobileDevice') is true) #don't do sortable on mobile
|
||||
['habit', 'daily', 'todo', 'reward'].forEach (type) ->
|
||||
$("ul.#{type}s").sortable
|
||||
dropOnEmpty: false
|
||||
cursor: "move"
|
||||
items: "li"
|
||||
scroll: true
|
||||
axis: 'y'
|
||||
update: (e, ui) ->
|
||||
item = ui.item[0]
|
||||
domId = item.id
|
||||
id = item.getAttribute 'data-id'
|
||||
to = $("ul.#{type}s").children().index(item)
|
||||
# Use the Derby ignore option to suppress the normal move event
|
||||
# binding, since jQuery UI will move the element in the DOM.
|
||||
# Also, note that refList index arguments can either be an index
|
||||
# or the item's id property
|
||||
model.at("_#{type}List").pass(ignore: domId).move {id}, to
|
||||
|
||||
setupTooltips = module.exports.setupTooltips = ->
|
||||
$('[rel=tooltip]').tooltip()
|
||||
$('[rel=popover]').popover()
|
||||
$('.popover-auto-show').popover('show')
|
||||
|
||||
$('.priority-multiplier-help').popover
|
||||
title: "How difficult is this task?"
|
||||
trigger: "hover"
|
||||
content: "This multiplies its point value. Use sparingly, rely instead on our organic value-adjustment algorithms. But some tasks are grossly more valuable (Write Thesis vs Floss Teeth). Click for more info."
|
||||
|
||||
setupTour = (model) ->
|
||||
tourSteps = [
|
||||
{
|
||||
|
|
@ -118,87 +84,9 @@ setupTour = (model) ->
|
|||
initStickyHeader = (model) ->
|
||||
$('.header-wrap').sticky({topSpacing:0})
|
||||
|
||||
growlNotification = module.exports.growlNotification = (html, type) ->
|
||||
$.bootstrapGrowl html,
|
||||
ele: '#notification-area',
|
||||
type: type # (null, 'info', 'error', 'success', 'gp', 'xp', 'hp', 'lvl','death')
|
||||
top_offset: 20
|
||||
align: 'right' # ('left', 'right', or 'center')
|
||||
width: 250 # (integer, or 'auto')
|
||||
delay: 3000
|
||||
allow_dismiss: true
|
||||
stackup_spacing: 10 # spacing between consecutive stacecked growls.
|
||||
|
||||
###
|
||||
Sets up "+1 Exp", "Level Up", etc notifications
|
||||
###
|
||||
setupGrowlNotifications = (model) ->
|
||||
return unless jQuery? # Only run this in the browser
|
||||
user = model.at '_user'
|
||||
|
||||
statsNotification = (html, type) ->
|
||||
return if user.get('stats.lvl') == 0 #don't show notifications if user dead
|
||||
growlNotification(html, type)
|
||||
|
||||
# Setup listeners which trigger notifications
|
||||
user.on 'set', 'stats.hp', (captures, args) ->
|
||||
num = captures - args
|
||||
rounded = Math.abs(num.toFixed(1))
|
||||
if num < 0
|
||||
statsNotification "<i class='icon-heart'></i> - #{rounded} HP", 'hp' # lost hp from purchase
|
||||
else if num > 0
|
||||
statsNotification "<i class='icon-heart'></i> + #{rounded} HP", 'hp' # gained hp from potion/level?
|
||||
|
||||
user.on 'set', 'stats.exp', (captures, args, isLocal, silent=false) ->
|
||||
# unless silent
|
||||
num = captures - args
|
||||
rounded = Math.abs(num.toFixed(1))
|
||||
if num < 0 and num > -50 # TODO fix hackey negative notification supress
|
||||
statsNotification "<i class='icon-star'></i> - #{rounded} XP", 'xp'
|
||||
else if num > 0
|
||||
statsNotification "<i class='icon-star'></i> + #{rounded} XP", 'xp'
|
||||
|
||||
###
|
||||
Show "+ 5 {gold_coin} 3 {silver_coin}"
|
||||
###
|
||||
showCoins = (money) ->
|
||||
absolute = Math.abs(money)
|
||||
gold = Math.floor(absolute)
|
||||
silver = Math.floor((absolute-gold)*100)
|
||||
if gold and silver > 0
|
||||
return "#{gold} <i class='icon-gold'></i> #{silver} <i class='icon-silver'></i>"
|
||||
else if gold > 0
|
||||
return "#{gold} <i class='icon-gold'></i>"
|
||||
else if silver > 0
|
||||
return "#{silver} <i class='icon-silver'></i>"
|
||||
|
||||
user.on 'set', 'stats.gp', (captures, args) ->
|
||||
money = captures - args
|
||||
return unless !!money # why is this happening? gotta find where stats.gp is being set from (-)habit
|
||||
sign = if money < 0 then '-' else '+'
|
||||
statsNotification "#{sign} #{showCoins(money)}", 'gp'
|
||||
|
||||
# Append Bonus
|
||||
bonus = model.get('_streakBonus')
|
||||
if (money > 0) and !!bonus
|
||||
bonus = 0.01 if bonus < 0.01
|
||||
statsNotification "+ #{showCoins(bonus)} Streak Bonus!"
|
||||
model.del('_streakBonus')
|
||||
|
||||
user.on 'set', 'items.*', (item, after, before) ->
|
||||
if item in ['armor','weapon','shield','head'] and parseInt(after) < parseInt(before)
|
||||
item = 'helm' if item is 'head' # don't want to day "lost a head"
|
||||
statsNotification "<i class='icon-death'></i> Respawn!", "death"
|
||||
|
||||
user.on 'set', 'stats.lvl', (captures, args) ->
|
||||
if captures > args
|
||||
statsNotification '<i class="icon-chevron-up"></i> Level Up!', 'lvl'
|
||||
|
||||
|
||||
|
||||
module.exports.app = (appExports, model, app) ->
|
||||
loadJavaScripts(model)
|
||||
setupGrowlNotifications(model) unless model.get('_mobileDevice')
|
||||
|
||||
app.on 'render', (ctx) ->
|
||||
#restoreRefs(model)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,118 @@
|
|||
'use strict';
|
||||
|
||||
habitrpg.controller('NotificationCtrl',
|
||||
['$scope', 'Notification',
|
||||
function ($scope, Notification) {
|
||||
$scope.data = Notification.get();
|
||||
['$scope', '$rootScope', 'User', function ($scope, $rootScope, User) {
|
||||
|
||||
function growlNotification(html, type) {
|
||||
$.bootstrapGrowl(html, {
|
||||
ele: '#notification-area',
|
||||
type: type, //(null, 'info', 'error', 'success', 'gp', 'xp', 'hp', 'lvl','death')
|
||||
top_offset: 20,
|
||||
align: 'right', //('left', 'right', or 'center')
|
||||
width: 250, //(integer, or 'auto')
|
||||
delay: 3000,
|
||||
allow_dismiss: true,
|
||||
stackup_spacing: 10 // spacing between consecutive stacecked growls.
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
Sets up "+1 Exp", "Level Up", etc notifications
|
||||
*/
|
||||
function setupGrowlNotifications() {
|
||||
|
||||
function statsNotification(html, type) {
|
||||
// don't show notifications if user dead
|
||||
if (User.user.stats.lvl == 0) return;
|
||||
growlNotification(html, type);
|
||||
};
|
||||
|
||||
/**
|
||||
Show "+ 5 {gold_coin} 3 {silver_coin}"
|
||||
*/
|
||||
function showCoins(money) {
|
||||
var absolute, gold, silver;
|
||||
absolute = Math.abs(money);
|
||||
gold = Math.floor(absolute);
|
||||
silver = Math.floor((absolute - gold) * 100);
|
||||
if (gold && silver > 0) {
|
||||
return "" + gold + " <i class='icon-gold'></i> " + silver + " <i class='icon-silver'></i>";
|
||||
} else if (gold > 0) {
|
||||
return "" + gold + " <i class='icon-gold'></i>";
|
||||
} else if (silver > 0) {
|
||||
return "" + silver + " <i class='icon-silver'></i>";
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.$watch('user.stats.hp', function(after, before) {
|
||||
if (after == before) return;
|
||||
var num = after - before;
|
||||
var rounded = Math.abs(num.toFixed(1));
|
||||
if (num < 0) {
|
||||
//lost hp from purchase
|
||||
statsNotification("<i class='icon-heart'></i> - " + rounded + " HP", 'hp');
|
||||
} else if (num > 0) {
|
||||
// gained hp from potion/level?
|
||||
statsNotification("<i class='icon-heart'></i> + " + rounded + " HP", 'hp');
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$watch('user.stats.exp', function(after, before) {
|
||||
if (after == before) return;
|
||||
var num = after - before;
|
||||
var rounded = Math.abs(num.toFixed(1));
|
||||
// TODO fix hackey negative notification supress
|
||||
if (num < 0 && num > -50) {
|
||||
statsNotification("<i class='icon-star'></i> - " + rounded + " XP", 'xp');
|
||||
} else if (num > 0) {
|
||||
statsNotification("<i class='icon-star'></i> + " + rounded + " XP", 'xp');
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$watch('user.stats.gp', function(after, before) {
|
||||
if (after == before) return;
|
||||
var bonus, money, sign;
|
||||
money = after - before;
|
||||
|
||||
//why is this happening? gotta find where stats.gp is being set from (-)habit
|
||||
//if (!money) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
sign = money < 0 ? '-' : '+';
|
||||
statsNotification("" + sign + " " + (showCoins(money)), 'gp');
|
||||
|
||||
//Append Bonus TODO
|
||||
//bonus = model.get('_streakBonus');
|
||||
|
||||
if ((money > 0) && !!bonus) {
|
||||
if (bonus < 0.01) {
|
||||
bonus = 0.01;
|
||||
}
|
||||
statsNotification("+ " + (showCoins(bonus)) + " Streak Bonus!");
|
||||
//model.del('_streakBonus');
|
||||
}
|
||||
});
|
||||
|
||||
// FIXME
|
||||
// user.on('set', 'items.*', function(item, after, before) {
|
||||
// if ((item === 'armor' || item === 'weapon' || item === 'shield' || item === 'head') && parseInt(after) < parseInt(before)) {
|
||||
// //don't want to day "lost a head"
|
||||
// if (item === 'head') {
|
||||
// item = 'helm';
|
||||
// }
|
||||
// return statsNotification("<i class='icon-death'></i> Respawn!", "death");
|
||||
// }
|
||||
// });
|
||||
|
||||
$rootScope.$watch('user.stats.lvl', function(after, before) {
|
||||
if (after == before) return;
|
||||
if (after > before) {
|
||||
statsNotification('<i class="icon-chevron-up"></i> Level Up!', 'lvl');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
setupGrowlNotifications();
|
||||
}
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -59,14 +59,17 @@ angular.module('userServices', []).
|
|||
sent.push(queue.shift());
|
||||
});
|
||||
|
||||
|
||||
$http.post(API_URL + '/api/v1/user/batch-update' + '?date=' + new Date().getTime(), sent)
|
||||
.success(function (data, status, heacreatingders, config) {
|
||||
data.tasks = _.toArray(data.tasks);
|
||||
//make sure there are no pending actions to sync. If there are any it is not safe to apply model from server as we may overwrite user data.
|
||||
if (!queue.length) {
|
||||
//we can't do user=data as it will not update user references in all other angular controllers.
|
||||
_.extend(user, data);
|
||||
|
||||
// FIXME - this is the one of the biggest issues in Habit rewrite right now, this function
|
||||
// kills CPU and makes it things un-responsive. We need to only update the user when it's been
|
||||
// modified, not every time. Commenting this out makes it out-of-sync with the API though
|
||||
//_.extend(user, data);
|
||||
|
||||
// FIXME handle this somewhere else, we don't need to check every single time
|
||||
var offset = moment().zone(); // eg, 240 - this will be converted on server as -(offset/60)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ html
|
|||
script(type='text/javascript', src='/bower_components/jquery/jquery.min.js')
|
||||
script(type='text/javascript', src='/bower_components/lodash/lodash.js')
|
||||
script(type='text/javascript', src='/bower_components/moment/moment.js')
|
||||
script(type='text/javascript', src='/bower_components/bootstrap-growl/jquery.bootstrap-growl.min.js')
|
||||
script(type='text/javascript', src='/bower_components/angular/angular.js')
|
||||
script(type='text/javascript', src='/bower_components/angular-route/angular-route.js')
|
||||
script(type='text/javascript', src='/bower_components/angular-resource/angular-resource.js')
|
||||
|
|
@ -75,7 +76,7 @@ html
|
|||
app:filters:filters(ng-hide='_gamePane')
|
||||
|
||||
br
|
||||
#notification-area
|
||||
#notification-area(ng-controller='NotificationCtrl')
|
||||
#wrap
|
||||
|
||||
// Errors
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ li(ng-repeat='task in user[list.type + "s"]', class='task {{taskClasses(task,use
|
|||
p.option-title.mega(ng-click='task._advanced = !task._advanced') Advanced Options
|
||||
fieldset.option-group.advanced-option(ng-class="{visuallyhidden: !task._advanced}")
|
||||
legend.option-title
|
||||
a.priority-multiplier-help(href='https://trello.com/card/priority-multiplier/50e5d3684fe3a7266b0036d6/17', target='_blank')
|
||||
a.priority-multiplier-help(href='https://trello.com/card/priority-multiplier/50e5d3684fe3a7266b0036d6/17', target='_blank', popover-title='How difficult is this task?', popover-trigger='mouseenter', popover="This multiplies its point value. Use sparingly, rely instead on our organic value-adjustment algorithms. But some tasks are grossly more valuable (Write Thesis vs Floss Teeth). Click for more info.")
|
||||
i.icon-question-sign
|
||||
| Difficulty
|
||||
// {{#if taskInChallenge(task)}}
|
||||
|
|
|
|||
Loading…
Reference in a new issue