mirror of https://github.com/perkeep/perkeep.git
start at twitter renderer.. pretty ugly right now. still working on it...
Change-Id: I7e4940d05bf0eb03f2eb68fb330a8fbe77c38173
This commit is contained in:
parent
3f1d8c14bc
commit
1138db00cd
|
@ -21,6 +21,7 @@ goog.require('goog.math.Size');
|
|||
goog.require('goog.object');
|
||||
goog.require('goog.string');
|
||||
|
||||
goog.require('cam.dateUtils');
|
||||
goog.require('cam.math');
|
||||
goog.require('cam.permanodeUtils');
|
||||
goog.require('cam.Thumber');
|
||||
|
@ -55,38 +56,10 @@ cam.BlobItemFoursquareContent = React.createClass({
|
|||
)
|
||||
)
|
||||
),
|
||||
React.DOM.div({className:'cam-blobitem-fs-checkin-when'}, this.formatDate_())
|
||||
React.DOM.div({className:'cam-blobitem-fs-checkin-when'}, cam.dateUtils.formatDateShort(this.props.date))
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
formatDate_: function() {
|
||||
var seconds = Math.floor((Date.now() - this.props.date) / 1000);
|
||||
var interval = Math.floor(seconds / 31536000);
|
||||
|
||||
return (function() {
|
||||
if (interval > 1) {
|
||||
return interval + ' years';
|
||||
}
|
||||
interval = Math.floor(seconds / 2592000);
|
||||
if (interval > 1) {
|
||||
return interval + ' months';
|
||||
}
|
||||
interval = Math.floor(seconds / 86400);
|
||||
if (interval > 1) {
|
||||
return interval + ' days';
|
||||
}
|
||||
interval = Math.floor(seconds / 3600);
|
||||
if (interval > 1) {
|
||||
return interval + ' hours';
|
||||
}
|
||||
interval = Math.floor(seconds / 60);
|
||||
if (interval > 1) {
|
||||
return interval + ' minutes';
|
||||
}
|
||||
return Math.floor(seconds) + ' seconds';
|
||||
})() + ' ago';
|
||||
},
|
||||
});
|
||||
|
||||
// Blech, we need this to prevent images from flashing when data changes server-side.
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
Copyright 2014 The Camlistore Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.cam-blobitem-twitter-tweet {
|
||||
color: black;
|
||||
display: block;
|
||||
font-size: 90%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
white-space: normal;
|
||||
border-radius: 7%;
|
||||
}
|
||||
|
||||
.cam-blobitem-twitter-tweet table {
|
||||
border-spacing: 0;
|
||||
background-color: #e1e8ed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cam-blobitem-twitter-tweet-icon {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.cam-blobitem-twitter-tweet-icon img {
|
||||
width: 4em;
|
||||
height: 4em;
|
||||
position: absolute;
|
||||
bottom: 1em;
|
||||
right: 1em;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.cam-blobitem-twitter-tweet-meta {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
padding: 0.8em;
|
||||
}
|
||||
|
||||
.cam-blobitem-twitter-tweet-date {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.cam-blobitem-twitter-tweet-image {
|
||||
background-position: top;
|
||||
background-size: cover;
|
||||
height: 100%;
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
Copyright 2014 The Camlistore Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
goog.provide('cam.BlobItemTwitterContent');
|
||||
|
||||
goog.require('goog.math.Size');
|
||||
|
||||
goog.require('cam.dateUtils');
|
||||
goog.require('cam.math');
|
||||
goog.require('cam.permanodeUtils');
|
||||
goog.require('cam.Thumber');
|
||||
|
||||
cam.BlobItemTwitterContent = React.createClass({
|
||||
propTypes: {
|
||||
date: React.PropTypes.number.isRequired,
|
||||
href: React.PropTypes.string.isRequired,
|
||||
image: React.PropTypes.string,
|
||||
size: React.PropTypes.instanceOf(goog.math.Size).isRequired,
|
||||
username: React.PropTypes.string.isRequired,
|
||||
},
|
||||
|
||||
getImageRow_: function() {
|
||||
if (!this.props.image) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return React.DOM.tr(null,
|
||||
React.DOM.td({
|
||||
className: 'cam-blobitem-twitter-tweet-image',
|
||||
colSpan: 2,
|
||||
src: 'twitter-icon.png',
|
||||
style: {
|
||||
backgroundImage: 'url(' + this.props.image + ')',
|
||||
},
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return React.DOM.a({
|
||||
href: this.props.href,
|
||||
className: 'cam-blobitem-twitter-tweet',
|
||||
style: {
|
||||
width: this.props.size.width,
|
||||
height: this.props.size.height,
|
||||
},
|
||||
},
|
||||
React.DOM.table({height: this.props.image ? '100%' : ''},
|
||||
React.DOM.tr(null,
|
||||
React.DOM.td({className: 'cam-blobitem-twitter-tweet-meta'},
|
||||
React.DOM.span({className: 'cam-blobitem-twitter-tweet-date'}, cam.dateUtils.formatDateShort(this.props.date)),
|
||||
React.DOM.br(),
|
||||
React.DOM.span({className: ' cam-blobitem-twitter-tweet-content'}, this.props.content)
|
||||
)
|
||||
),
|
||||
this.getImageRow_(),
|
||||
React.DOM.tr(null,
|
||||
React.DOM.td({className: 'cam-blobitem-twitter-tweet-icon'},
|
||||
React.DOM.img({src: 'twitter-logo.png'})
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
cam.BlobItemTwitterContent.getHandler = function(blobref, searchSession, href) {
|
||||
var m = searchSession.getMeta(blobref);
|
||||
if (m.camliType != 'permanode') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cam.permanodeUtils.getSingleAttr(m.permanode, 'camliNodeType') != 'twitter.com:tweet') {
|
||||
return null;
|
||||
}
|
||||
|
||||
var content = cam.permanodeUtils.getSingleAttr(m.permanode, 'content');
|
||||
var date = cam.permanodeUtils.getSingleAttr(m.permanode, 'startDate');
|
||||
var username = cam.permanodeUtils.getSingleAttr(m.permanode, 'url').match(/^https:\/\/twitter.com\/(.+?)\//)[1];
|
||||
var imageMeta = cam.permanodeUtils.getSingleAttr(m.permanode, 'camliContentImage');
|
||||
if (imageMeta) {
|
||||
imageMeta = searchSession.getResolvedMeta(imageMeta);
|
||||
}
|
||||
|
||||
return new cam.BlobItemTwitterContent.Handler(content, Date.parse(date), href, imageMeta, username);
|
||||
};
|
||||
|
||||
cam.BlobItemTwitterContent.Handler = function(content, date, href, imageMeta, username) {
|
||||
this.content_ = content;
|
||||
this.date_ = date;
|
||||
this.href_ = href;
|
||||
this.username_ = username;
|
||||
this.thumber_ = imageMeta ? new cam.Thumber.fromImageMeta(imageMeta) : null;
|
||||
};
|
||||
|
||||
cam.BlobItemTwitterContent.Handler.prototype.getAspectRatio = function() {
|
||||
return 1.0;
|
||||
};
|
||||
|
||||
cam.BlobItemTwitterContent.Handler.prototype.createContent = function(size) {
|
||||
return cam.BlobItemTwitterContent({
|
||||
content: this.content_,
|
||||
date: this.date_,
|
||||
href: this.href_,
|
||||
image: this.thumber_ ? this.thumber_.getSrc(size) : null,
|
||||
size: size,
|
||||
username: this.username_,
|
||||
});
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
Copyright 2014 The Camlistore Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
goog.provide('cam.dateUtils');
|
||||
|
||||
cam.dateUtils.formatDateShort = function(date) {
|
||||
// TODO(aa): Do something better based on Closure date/i18n utils.
|
||||
// I think I would prefer this to return (in en-us) either '11:18 PM', 'Jun 11', or 'June 11 1952', depending on how far back it is. I don't find '5 hours ago' that useful.
|
||||
var seconds = Math.floor((Date.now() - date) / 1000);
|
||||
var interval = Math.floor(seconds / 31536000);
|
||||
|
||||
return (function() {
|
||||
if (interval > 1) {
|
||||
return interval + ' years';
|
||||
}
|
||||
interval = Math.floor(seconds / 2592000);
|
||||
if (interval > 1) {
|
||||
return interval + ' months';
|
||||
}
|
||||
interval = Math.floor(seconds / 86400);
|
||||
if (interval > 1) {
|
||||
return interval + ' days';
|
||||
}
|
||||
interval = Math.floor(seconds / 3600);
|
||||
if (interval > 1) {
|
||||
return interval + ' hours';
|
||||
}
|
||||
interval = Math.floor(seconds / 60);
|
||||
if (interval > 1) {
|
||||
return interval + ' minutes';
|
||||
}
|
||||
return Math.floor(seconds) + ' seconds';
|
||||
})() + ' ago';
|
||||
};
|
|
@ -40,6 +40,7 @@ limitations under the License.
|
|||
<link rel="stylesheet" href="blob_item_video.css" type="text/css">
|
||||
<link rel="stylesheet" href="blob_item_container.css" type="text/css">
|
||||
<link rel="stylesheet" href="blob_item_foursquare.css" type="text/css">
|
||||
<link rel="stylesheet" href="blob_item_twitter.css" type="text/css">
|
||||
<link rel="stylesheet" href="detail.css" type="text/css">
|
||||
<link rel="stylesheet" href="index.css" type="text/css">
|
||||
<link rel="stylesheet" href="nav.css" type="text/css">
|
||||
|
|
|
@ -26,11 +26,12 @@ goog.require('goog.Uri');
|
|||
|
||||
goog.require('cam.BlobDetail');
|
||||
goog.require('cam.BlobItemContainerReact');
|
||||
goog.require('cam.BlobItemDemoContent');
|
||||
goog.require('cam.BlobItemFoursquareContent');
|
||||
goog.require('cam.BlobItemGenericContent');
|
||||
goog.require('cam.BlobItemVideoContent');
|
||||
goog.require('cam.BlobItemImageContent');
|
||||
goog.require('cam.BlobItemDemoContent');
|
||||
goog.require('cam.BlobItemTwitterContent');
|
||||
goog.require('cam.BlobItemVideoContent');
|
||||
goog.require('cam.ContainerDetail');
|
||||
goog.require('cam.DetailView');
|
||||
goog.require('cam.DirectoryDetail');
|
||||
|
@ -53,12 +54,14 @@ cam.IndexPage = React.createClass({
|
|||
RAW: 'raw'
|
||||
},
|
||||
|
||||
// Note that these are ordered by priority.
|
||||
BLOB_ITEM_HANDLERS_: [
|
||||
cam.BlobItemDemoContent.getHandler,
|
||||
cam.BlobItemFoursquareContent.getHandler,
|
||||
cam.BlobItemTwitterContent.getHandler,
|
||||
cam.BlobItemImageContent.getHandler,
|
||||
cam.BlobItemVideoContent.getHandler,
|
||||
cam.BlobItemGenericContent.getHandler // must be last
|
||||
cam.BlobItemGenericContent.getHandler
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
Loading…
Reference in New Issue