Skip to content

Commit 8e1fae0

Browse files
committed
Add Discourse.Singleton class mixin for creating singletons.
1 parent 9564a6c commit 8e1fae0

10 files changed

Lines changed: 90 additions & 52 deletions

File tree

app/assets/javascripts/discourse/components/screen_track.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ Discourse.ScreenTrack = Ember.Object.extend({
9898
highestSeen = Math.max(highestSeen, parseInt(postNumber, 10));
9999
});
100100

101-
var highestSeenByTopic = Discourse.Session.current('highestSeenByTopic');
101+
var highestSeenByTopic = Discourse.Session.currentProp('highestSeenByTopic');
102102
if ((highestSeenByTopic[topicId] || 0) < highestSeen) {
103103
highestSeenByTopic[topicId] = highestSeen;
104104
Discourse.TopicTrackingState.current().updateSeen(topicId, highestSeen);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
This mixin allows a class to return a singleton, as well as a method to quickly
3+
read/write attributes on the singleton.
4+
5+
@class Discourse.Singleton
6+
@extends Ember.Mixin
7+
@namespace Discourse
8+
@module Discourse
9+
**/
10+
Discourse.Singleton = Em.Mixin.create({
11+
12+
/**
13+
Returns the current singleton instance of the class.
14+
15+
@method current
16+
@returns {Ember.Object} the instance of the singleton
17+
**/
18+
current: function() {
19+
if (!this._current) {
20+
this._current = this.create({});
21+
}
22+
23+
return this._current;
24+
},
25+
26+
/**
27+
Returns or sets a property on the singleton instance.
28+
29+
@method currentProp
30+
@param {String} property the property we want to get or set
31+
@param {String} value the optional value to set the property to
32+
@returns the value of the property
33+
**/
34+
currentProp: function(property, value) {
35+
if (typeof(value) !== "undefined") {
36+
this.current().set(property, value);
37+
return value;
38+
} else {
39+
return this.current().get(property);
40+
}
41+
}
42+
43+
});
44+
45+
Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
A data model representing current session data. You can put transient
3-
data here you might want later.
3+
data here you might want later. It is not stored or serialized anywhere.
44
55
@class Session
66
@extends Discourse.Model
@@ -13,28 +13,4 @@ Discourse.Session = Discourse.Model.extend({
1313
}
1414
});
1515

16-
Discourse.Session.reopenClass({
17-
18-
/**
19-
Returns the current session.
20-
21-
@method current
22-
@returns {Discourse.Session} the current session singleton
23-
**/
24-
current: function(property, value) {
25-
if (!this.currentSession) {
26-
this.currentSession = Discourse.Session.create();
27-
}
28-
29-
// If we found the current session
30-
if (typeof property !== "undefined") {
31-
if (typeof value !== "undefined") {
32-
this.currentSession.set(property, value);
33-
} else {
34-
return this.currentSession.get(property);
35-
}
36-
}
37-
38-
return property ? this.currentSession.get(property) : this.currentSession;
39-
}
40-
});
16+
Discourse.Session.reopenClass(Discourse.Singleton);

app/assets/javascripts/discourse/models/topic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Discourse.Topic = Discourse.Model.extend({
8787
// So take what the browser has seen into consideration.
8888
displayNewPosts: function() {
8989
var delta, highestSeen, result;
90-
if (highestSeen = Discourse.Session.current('highestSeenByTopic')[this.get('id')]) {
90+
if (highestSeen = Discourse.Session.currentProp('highestSeenByTopic')[this.get('id')]) {
9191
delta = highestSeen - this.get('last_read_post_number');
9292
if (delta > 0) {
9393
result = this.get('new_posts') - delta;

app/assets/javascripts/discourse/models/topic_list.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Discourse.TopicList = Discourse.Model.extend({
4545
});
4646

4747
topicList.set('more_topics_url', result.topic_list.more_topics_url);
48-
Discourse.Session.current('topicList', topicList);
48+
Discourse.Session.currentProp('topicList', topicList);
4949
topicList.set('loadingMore', false);
5050

5151
return result.topic_list.more_topics_url;
@@ -75,7 +75,7 @@ Discourse.TopicList = Discourse.Model.extend({
7575
t.set('highlight', true);
7676
topics.insertAt(0,t);
7777
});
78-
Discourse.Session.current('topicList', topicList);
78+
Discourse.Session.currentProp('topicList', topicList);
7979
});
8080
}
8181
});

app/assets/javascripts/discourse/routes/filtered_list_route.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Discourse.FilteredListRoute = Discourse.Route.extend({
4141
listController.set('canCreateTopic', topicList.get('can_create_topic'));
4242
listTopicsController.set('model', topicList);
4343

44-
var scrollPos = Discourse.Session.current('topicListScrollPosition');
44+
var scrollPos = Discourse.Session.currentProp('topicListScrollPosition');
4545
if (scrollPos) {
4646
Em.run.next(function() {
4747
$('html, body').scrollTop(scrollPos);

app/assets/javascripts/discourse/routes/topic_route.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Discourse.TopicRoute = Discourse.Route.extend({
7171
this._super();
7272

7373
var topic = this.modelFor('topic');
74-
Discourse.Session.current('lastTopicIdViewed', parseInt(topic.get('id'), 10));
74+
Discourse.Session.currentProp('lastTopicIdViewed', parseInt(topic.get('id'), 10));
7575
this.controllerFor('search').set('searchContext', topic.get('searchContext'));
7676
},
7777

app/mailers/user_notifications.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ class UserNotificationRenderer < ActionView::Base
100100
end
101101

102102
def notification_email(user, opts)
103-
104103
return unless @notification = opts[:notification]
105104
return unless @post = opts[:post]
106105

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module("Discourse.Singleton");
2+
3+
test("current", function() {
4+
var DummyModel = Ember.Object.extend({});
5+
DummyModel.reopenClass(Discourse.Singleton);
6+
7+
var current = DummyModel.current();
8+
present(current, 'current returns the current instance');
9+
equal(current, DummyModel.current(), 'calling it again returns the same instance');
10+
notEqual(current, DummyModel.create({}), 'we can create other instances that are not the same as current');
11+
});
12+
13+
test("currentProp reading", function() {
14+
var DummyModel = Ember.Object.extend({});
15+
DummyModel.reopenClass(Discourse.Singleton);
16+
var current = DummyModel.current();
17+
18+
blank(DummyModel.currentProp('evil'), 'by default attributes are blank');
19+
current.set('evil', 'trout');
20+
equal(DummyModel.currentProp('evil'), 'trout', 'after changing the instance, the value is set');
21+
});
22+
23+
test("currentProp writing", function() {
24+
var DummyModel = Ember.Object.extend({});
25+
DummyModel.reopenClass(Discourse.Singleton);
26+
27+
blank(DummyModel.currentProp('adventure'), 'by default attributes are blank');
28+
var result = DummyModel.currentProp('adventure', 'time');
29+
equal(result, 'time', 'it returns the new value');
30+
equal(DummyModel.currentProp('adventure'), 'time', 'after calling currentProp the value is set');
31+
32+
DummyModel.currentProp('count', 0);
33+
equal(DummyModel.currentProp('count'), 0, 'we can set the value to 0');
34+
35+
DummyModel.currentProp('adventure', null);
36+
equal(DummyModel.currentProp('adventure'), null, 'we can set the value to null');
37+
});
Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,6 @@
11
module("Discourse.Session");
22

3-
test('current', function(){
4-
var session = Discourse.Session.current();
5-
6-
present(session, "We have a current site session");
7-
equal(session, Discourse.Session.current(), "Calling it a second time returns the same instance");
8-
9-
blank(Discourse.Session.current('orange'), "by default properties are nil");
10-
session.set('orange', 'newBlack');
11-
equal(Discourse.Session.current('orange'), "newBlack", "it remembers values");
12-
13-
Discourse.Session.current('orange', 'juice');
14-
equal(session.get('orange'), "juice", "it can be updated");
15-
16-
Discourse.Session.current('zero', 0);
17-
equal(session.get('zero'), 0);
18-
});
19-
203
test('highestSeenByTopic', function() {
21-
224
var session = Discourse.Session.current();
235
deepEqual(session.get('highestSeenByTopic'), {}, "by default it returns an empty object");
24-
256
});

0 commit comments

Comments
 (0)