diff --git a/app/assets/javascripts/app/pages/single-post-viewer.js b/app/assets/javascripts/app/pages/single-post-viewer.js
new file mode 100644
index 000000000..2c68fb158
--- /dev/null
+++ b/app/assets/javascripts/app/pages/single-post-viewer.js
@@ -0,0 +1,40 @@
+app.pages.SinglePostViewer = app.views.Base.extend({
+ templateName: "single-post-viewer",
+
+ subviews : {
+ "#single-post-content" : "singlePostContentView",
+ '#single-post-interactions' : 'singlePostInteractionsView'
+ },
+
+ initialize : function(options) {
+ this.model = new app.models.Post({ id : options.id });
+ this.model.preloadOrFetch().done(_.bind(this.initViews, this));
+ this.model.interactions.fetch() //async, yo, might want to throttle this later.
+ this.setupLightbox()
+ },
+
+ setupLightbox : function(){
+ this.lightbox = Diaspora.BaseWidget.instantiate("Lightbox");
+ this.lightbox.set({
+ imageParent: '.photo_attachments',
+ imageSelector: 'img.stream-photo'
+ });
+ this.$el.delegate("a.stream-photo-link", "click", this.lightbox.lightboxImageClicked);
+ },
+
+ initViews : function() {
+ this.singlePostContentView = new app.views.SinglePostContent({model: this.model});
+ this.singlePostInteractionsView = new app.views.SinglePostInteractions({model: this.model});
+ this.render();
+ },
+
+ postRenderTemplate : function() {
+ if(this.model.get("title")){
+ // formats title to html...
+ var html_title = app.helpers.textFormatter(this.model.get("title"), this.model);
+ //... and converts html to plain text
+ document.title = $('
').html(html_title).text();
+ }
+ },
+
+});
diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_actions.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_actions.js
new file mode 100644
index 000000000..054ddf150
--- /dev/null
+++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_actions.js
@@ -0,0 +1,3 @@
+app.views.SinglePostActions = app.views.Feedback.extend({
+ templateName: "single-post-viewer/single-post-actions",
+});
diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js
new file mode 100644
index 000000000..787f7b004
--- /dev/null
+++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_comment_stream.js
@@ -0,0 +1,15 @@
+app.views.SinglePostCommentStream = app.views.CommentStream.extend({
+
+ postRenderTemplate: function() {
+ app.views.CommentStream.prototype.postRenderTemplate.apply(this)
+ this.$(".new_comment_form_wrapper").removeClass('hidden')
+ },
+
+ presenter: function(){
+ return _.extend(this.defaultPresenter(), {
+ moreCommentsCount : 0,
+ showExpandCommentsLink : false,
+ commentsCount : this.model.interactions.commentsCount()
+ })
+ },
+})
diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js
new file mode 100644
index 000000000..c04d63dd7
--- /dev/null
+++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_content_view.js
@@ -0,0 +1,33 @@
+app.views.SinglePostContent = app.views.Base.extend({
+ templateName: 'single-post-viewer/single-post-content',
+
+ subviews : {
+ "#single-post-actions" : "singlePostActionsView",
+ '#real-post-content' : 'postContentView',
+ ".oembed" : "oEmbedView",
+ ".opengraph" : "openGraphView"
+ },
+
+ initialize : function() {
+ this.singlePostActionsView = new app.views.SinglePostActions({model: this.model});
+ this.oEmbedView = new app.views.OEmbed({model : this.model});
+ this.openGraphView = new app.views.OpenGraph({model : this.model});
+ this.postContentView = new app.views.StatusMessage({model: this.model});
+ },
+
+ presenter : function() {
+ return _.extend(this.defaultPresenter(), {
+ authorIsCurrentUser : this.authorIsCurrentUser(),
+ showPost : this.showPost(),
+ text : app.helpers.textFormatter(this.model.get("text"), this.model)
+ })
+ },
+
+ authorIsCurrentUser : function() {
+ return app.currentUser.authenticated() && this.model.get("author").id == app.user().id
+ },
+
+ showPost : function() {
+ return (app.currentUser.get("showNsfw")) || !this.model.get("nsfw")
+ }
+});
diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_interactions.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_interactions.js
new file mode 100644
index 000000000..3ca98b952
--- /dev/null
+++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_interactions.js
@@ -0,0 +1,24 @@
+app.views.SinglePostInteractions = app.views.Base.extend({
+ templateName: "single-post-viewer/single-post-interactions",
+
+ subviews: {
+ '#comments': 'commentStreamView'
+ },
+
+ initialize : function() {
+ this.model.interactions.on('change', this.render, this);
+ this.commentStreamView = new app.views.SinglePostCommentStream({model: this.model})
+ },
+
+ presenter : function(){
+ var interactions = this.model.interactions
+ return {
+ likes : interactions.likes.toJSON(),
+ comments : interactions.comments.toJSON(),
+ reshares : interactions.reshares.toJSON(),
+ commentsCount : interactions.commentsCount(),
+ likesCount : interactions.likesCount(),
+ resharesCount : interactions.resharesCount(),
+ }
+ },
+});
diff --git a/app/assets/templates/single-post-viewer/single-post-actions_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-actions_tpl.jst.hbs
new file mode 100644
index 000000000..cd4609447
--- /dev/null
+++ b/app/assets/templates/single-post-viewer/single-post-actions_tpl.jst.hbs
@@ -0,0 +1,24 @@
+
diff --git a/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs
new file mode 100644
index 000000000..abf755b7e
--- /dev/null
+++ b/app/assets/templates/single-post-viewer/single-post-content_tpl.jst.hbs
@@ -0,0 +1,36 @@
+
+
+
+ {{#linkToPerson author}}
+
+ {{/linkToPerson}}
+
+
+
+ {{#linkToPerson author}}
+ {{name}}
+ {{/linkToPerson}}
+
+ {{#if root}}
+
+
+ {{#linkToPerson root.author}}
+ {{name}}
+ {{/linkToPerson}}
+
+ {{/if}}
+
+
+ {{#unless public}}
+
+ {{/unless}}
+
+
+
+
+
+
+
diff --git a/app/assets/templates/single-post-viewer/single-post-interactions_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-interactions_tpl.jst.hbs
new file mode 100644
index 000000000..e31284151
--- /dev/null
+++ b/app/assets/templates/single-post-viewer/single-post-interactions_tpl.jst.hbs
@@ -0,0 +1,29 @@
+
+
+
+ {{resharesCount}}
+
+ {{#each reshares}}
+ {{{personImage author 'small' "micro"}}}
+ {{/each}}
+
+
+
+
+ {{likesCount}}
+
+ {{#each likes}}
+ {{{personImage author 'small' "micro"}}}
+ {{/each}}
+
+
+
diff --git a/app/assets/templates/single-post-viewer_tpl.jst.hbs b/app/assets/templates/single-post-viewer_tpl.jst.hbs
new file mode 100644
index 000000000..322d96367
--- /dev/null
+++ b/app/assets/templates/single-post-viewer_tpl.jst.hbs
@@ -0,0 +1,8 @@
+