mirror of
https://github.com/twisterarmy/swizzler.git
synced 2025-03-11 21:11:01 +00:00
User fullname and avatar are now in an iframe
Great performance boost. Also: * Input field to copy @username Once we can post, this may be handy * Search is also an iframe (containing an iframe per user) So you can keep composing a twist while searching for usernames * Should be responsive for cellulars (I can only resize browser to check. Got no phone. Anyway, the floating "Fork me" footer now has a link to navigation (local users), and that's about all the essential navigation. You can scroll a bit down from there for search results, or all the way up for the content. * Make sure Dillo etc. that don't see bootstrap font icon can still have text links to everything Enjoy
This commit is contained in:
parent
1c5d43e0e0
commit
3ffb1e6524
@ -1,5 +1,6 @@
|
||||
body {padding-top:8px; background:#eef url(/assets/img/swizzler-128.png) no-repeat fixed right bottom}
|
||||
.avatar {max-width:64px; max-height:64px}
|
||||
.avatars32 .avatar {max-width:32px; max-height:32px}
|
||||
.avatars42 .avatar {max-width:44px; max-height:44px}
|
||||
.panel, .list-group-item { background-color: rgba(255,255,255,0.33) } /* I should be doing this by customizing bootstrap. Later :) */
|
||||
#footer {z-index:115;position:fixed;right:123px;bottom:0}
|
||||
#footer {z-index:115;position:fixed;right:96px;bottom:8px}
|
||||
|
79
swizzler.py
79
swizzler.py
@ -12,19 +12,19 @@ from ttp import ttp
|
||||
class TwistParser(ttp.Parser):
|
||||
def format_tag(self, tag, text):
|
||||
'''Return formatted HTML for a hashtag.'''
|
||||
return '<a href="{0}/tag/{1}">{2}{3}</a>'.format(
|
||||
return '<a target="_top" href="{0}/tag/{1}">{2}{3}</a>'.format(
|
||||
cherrypy.request.base+cherrypy.request.script_name,
|
||||
ttp.urllib.quote(text.lower().encode('utf-8'),'xmlcharrefreplace'), tag, text)
|
||||
|
||||
def format_username(self, at_char, user):
|
||||
'''Return formatted HTML for a username.'''
|
||||
return '<a href="{0}/user/{1}">{2}{3}</a>'.format(
|
||||
return '<a target="_top" href="{0}/user/{1}">{2}{3}</a>'.format(
|
||||
cherrypy.request.base+cherrypy.request.script_name,
|
||||
user, at_char, user.lower())
|
||||
|
||||
def format_list(self, at_char, user, list_name):
|
||||
'''We don't have lists, so we see it as "@user" followed by "/something"'''
|
||||
return '<a href="{0}/user/{1}">{2}{3}</a>/{4}'.format(
|
||||
return '<a target="_top" href="{0}/user/{1}">{2}{3}</a>/{4}'.format(
|
||||
cherrypy.request.base+cherrypy.request.script_name,
|
||||
cherrypy.request.base+cherrypy.request.script_name, user, at_char, user.lower(), list_name)
|
||||
|
||||
@ -45,47 +45,47 @@ def format_trending(twister,num_messages=8):
|
||||
|
||||
### The Swizzler app
|
||||
class SwizzlerApp(object):
|
||||
def _standard_params(self,twister,q,num_items=8):
|
||||
@cherrypy.expose
|
||||
def search(self,q=''):
|
||||
conf = cherrypy.request.app.config['swizzler']
|
||||
twister = Twister(conf['rpc_url'],format_twist)
|
||||
result = {'site_root':cherrypy.request.base+cherrypy.request.script_name}
|
||||
result['here'] = result['site_root']+cherrypy.request.path_info
|
||||
q=(q or '').strip().split(' ')[0] # ignore anything after the first space if any
|
||||
q = q.strip().split(' ')[0] # ignore anything after the first space if any
|
||||
if q.startswith('#'): # user said "#sometag", change to "sometag"
|
||||
q=q[1:]
|
||||
if q and not q.startswith('@'): # Tag. redirect.
|
||||
raise cherrypy.HTTPRedirect(result['site_root']+'/tag/{0}'.format(q))
|
||||
if q:
|
||||
result['user_prefix'] = q
|
||||
result['users'] = twister.get_users_by_partial_name(q[1:],num_items)
|
||||
return result
|
||||
result['trending'] = format_trending(twister,num_items)
|
||||
return result
|
||||
|
||||
result['users'] = twister.get_users_by_partial_name(q[1:],conf['num_messages'])
|
||||
else:
|
||||
result['trending'] = format_trending(twister,conf['num_messages'])
|
||||
return stache.render(stache.load_template('search'),result)
|
||||
|
||||
@cherrypy.expose
|
||||
def twist(self,username,k,q=None):
|
||||
def twist(self,username,k):
|
||||
conf = cherrypy.request.app.config['swizzler']
|
||||
twister = Twister(conf['rpc_url'],format_twist)
|
||||
params = self._standard_params(twister,q,conf['num_messages']) # called as soon as possible, because it might raise a redirect
|
||||
twist = twister.get_twist(username,k)
|
||||
twist['style_large'] = True
|
||||
rts = twister.get_twist_rts(username,k)
|
||||
print rts
|
||||
result = {
|
||||
'is_twist':True,
|
||||
'title':u"@{0}: {1} - Swizzler".format(twist['user']['username'],twist['time']),
|
||||
'title':u"@{0}: {1} - Swizzler".format(username,twist['time']),
|
||||
'twist':twist,
|
||||
'in_reply_to':twist.get('reply') and twister.get_twist(twist['reply']['user']['username'],twist['reply']['k']) or None,
|
||||
'in_reply_to':twist.get('reply') and twister.get_twist(twist['reply']['username'],twist['reply']['k']) or None,
|
||||
'replies':twister.get_twist_replies(username,k),
|
||||
'rts':rts,
|
||||
'any_rts':not not rts,
|
||||
'local_users':twister.local_user_menu()['users'],
|
||||
'info':twister.get_info(),
|
||||
'site_root':cherrypy.request.base+cherrypy.request.script_name,
|
||||
}
|
||||
result.update(params)
|
||||
return stache.render(stache.load_template('twist'),result)
|
||||
@cherrypy.expose
|
||||
def user(self,username,q=None):
|
||||
def user(self,username):
|
||||
conf = cherrypy.request.app.config['swizzler']
|
||||
twister = Twister(conf['rpc_url'],format_twist)
|
||||
params = self._standard_params(twister,q,conf['num_messages']) # called as soon as possible, because it might raise a redirect
|
||||
user = twister.get_user_info(username)
|
||||
messages = twister.get_user_posts(username,conf['num_messages'])
|
||||
result = {
|
||||
@ -96,14 +96,26 @@ class SwizzlerApp(object):
|
||||
'any_messages':not not messages,
|
||||
'local_users':twister.local_user_menu()['users'],
|
||||
'info':twister.get_info(),
|
||||
'site_root':cherrypy.request.base+cherrypy.request.script_name,
|
||||
}
|
||||
result.update(params)
|
||||
return stache.render(stache.load_template('standard'),result)
|
||||
@cherrypy.expose
|
||||
def tag(self,tag,q=None):
|
||||
def user_embed(self,username='nobody',style='normal'):
|
||||
if username=='nobody': username='' # to enable /nobody/large
|
||||
conf = cherrypy.request.app.config['swizzler']
|
||||
twister = Twister(conf['rpc_url'],format_twist)
|
||||
user = twister.get_user_info(username)
|
||||
result = {
|
||||
'title':'@{0} - Swizzler'.format(username),
|
||||
'site_root':cherrypy.request.base+cherrypy.request.script_name,
|
||||
'user':twister.get_user_info(username)
|
||||
}
|
||||
result['style_{0}'.format(style)] = True
|
||||
return stache.render(stache.load_template('user-iframe'),result)
|
||||
@cherrypy.expose
|
||||
def tag(self,tag):
|
||||
conf = cherrypy.request.app.config['swizzler']
|
||||
twister = Twister(conf['rpc_url'],format_twist)
|
||||
params = self._standard_params(twister,q,conf['num_messages']) # called as soon as possible, because it might raise a redirect
|
||||
messages = twister.get_tag_posts(tag)
|
||||
result = {
|
||||
'is_tag':True,
|
||||
@ -113,15 +125,13 @@ class SwizzlerApp(object):
|
||||
'any_messages':not not messages,
|
||||
'local_users':twister.local_user_menu()['users'],
|
||||
'info':twister.get_info(),
|
||||
#the filter avoids some utf etc. that ttf can't handle (TODO: fix or replace format_twist)
|
||||
'site_root':cherrypy.request.base+cherrypy.request.script_name,
|
||||
}
|
||||
result.update(params)
|
||||
return stache.render(stache.load_template('standard'),result)
|
||||
@cherrypy.expose
|
||||
def home(self,localusername,mode='feed',q=None):
|
||||
def home(self,localusername,mode='feed'):
|
||||
conf = cherrypy.request.app.config['swizzler']
|
||||
twister = Twister(conf['rpc_url'],format_twist)
|
||||
params = self._standard_params(twister,q,conf['num_messages']) # called as soon as possible, because it might raise a redirect
|
||||
menu = twister.local_user_menu(localusername)
|
||||
if mode=='mentions':
|
||||
messages = twister.get_user_mentions(localusername)
|
||||
@ -131,20 +141,19 @@ class SwizzlerApp(object):
|
||||
'is_home':True,
|
||||
'is_mentions':mode=='mentions',
|
||||
'is_feed':mode!='mentions',
|
||||
'title':u"{fullname} (@{username}): Home - Swizzler".format(**menu['active']),
|
||||
'title':u"{fullname} (@{username}): {mode} - Swizzler".format(mode=mode=='mentions' and 'Mentions' or 'Home',**menu['active']),
|
||||
'local_users':menu['users'],
|
||||
'info':twister.get_info(),
|
||||
'subject':menu['active'],
|
||||
'messages':messages,
|
||||
'any_messages':not not messages,
|
||||
'site_root':cherrypy.request.base+cherrypy.request.script_name,
|
||||
}
|
||||
result.update(params)
|
||||
return stache.render(stache.load_template('standard'),result)
|
||||
@cherrypy.expose
|
||||
def messages(self,localusername,remoteusername=None,q=None):
|
||||
def messages(self,localusername,remoteusername=None):
|
||||
conf = cherrypy.request.app.config['swizzler']
|
||||
twister = Twister(conf['rpc_url'],format_twist)
|
||||
params = self._standard_params(twister,q,conf['num_messages']) # called as soon as possible, because it might raise a redirect
|
||||
localuser = twister.get_user_info(localusername)
|
||||
remoteuser = remoteusername and twister.get_user_info(remoteusername) or None
|
||||
threads = remoteusername and twister.get_user_messages(localusername,remoteusername,conf['num_messages']) or twister.get_user_messages(localusername)
|
||||
@ -158,18 +167,17 @@ class SwizzlerApp(object):
|
||||
'any_threads':not not threads,
|
||||
'local_users':twister.local_user_menu()['users'],
|
||||
'info':twister.get_info(),
|
||||
#the filter avoids some utf etc. that ttf can't handle (TODO: fix or replace format_twist)
|
||||
'site_root':cherrypy.request.base+cherrypy.request.script_name,
|
||||
}
|
||||
result.update(params)
|
||||
return stache.render(stache.load_template('messages'),result)
|
||||
@cherrypy.expose
|
||||
def index(self,q=None):
|
||||
def index(self):
|
||||
conf = cherrypy.request.app.config['swizzler']
|
||||
twister = Twister(conf['rpc_url'],format_twist)
|
||||
params = self._standard_params(twister,q,conf['num_messages']) # called as soon as possible, because it might raise a redirect
|
||||
messages = twister.get_sponsored_posts(conf['num_messages'])
|
||||
result = {
|
||||
'is_user':True, # i.e. we want to display "bio" and not mentions/DMs/profile buttons
|
||||
'is_sponsored':True, # message template needs to know not to show "permalink"
|
||||
'title':"Welcome to Swizzler",
|
||||
'local_users':twister.local_user_menu('')['users'], # '' means: "Nobody" is active
|
||||
'info':twister.get_info(),
|
||||
@ -184,9 +192,8 @@ Start mining today, and all this (AND moral satisfaction) can be yours.""")
|
||||
},
|
||||
'messages':messages,
|
||||
'any_messages':not not messages,
|
||||
#the filter avoids some utf etc. that ttf can't handle (TODO: fix or replace format_twist)
|
||||
'site_root':cherrypy.request.base+cherrypy.request.script_name,
|
||||
}
|
||||
result.update(params)
|
||||
return stache.render(stache.load_template('standard'),result)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -1,3 +1,4 @@
|
||||
<footer id="footer">
|
||||
<div class="alert alert-info"><a target="_blank" href="https://github.com/swizzler/swizzler#readme"><strong>Fork</strong></a> this. Swizzler is <a target="_blank" href="http://www.gnu.org/licenses/agpl-3.0.html"><strong>AGPLV3</strong></a>.</span>
|
||||
<a class="btn btn-primary btn-sm" title="Scroll to navigation" href="#localusers"><span class="glyphicon glyphicon-th-list"></span></a>
|
||||
<a class="badge" target="_blank" title="Fork it like you mean it" href="https://github.com/swizzler/swizzler#readme"><span class="glyphicon glyphicon-wrench"></a>
|
||||
</footer>
|
||||
|
@ -1,45 +1,37 @@
|
||||
<li class="list-group-item media">
|
||||
{{#user}}
|
||||
<iframe class="thumbnail media-object {{#fromMe}}pull-right{{/fromMe}}{{^fromMe}}pull-left{{/fromMe}}"
|
||||
style="border:none; padding:0; background:none; overflow:hidden"
|
||||
width=33% height={{#style_large}}96{{/style_large}}{{^style_large}}72{{/style_large}} seamless=seamless
|
||||
src="{{site_root}}/user_embed/{{username}}{{^username}}nobody{{/username}}{{#style_large}}/large{{/style_large}}{{#fromMe}}/from_me{{/fromMe}}"></iframe>
|
||||
<div class="media-body">
|
||||
{{#username}}
|
||||
<a class="{{#fromMe}}pull-right{{/fromMe}}{{^fromMe}}pull-left{{/fromMe}} thumbnail" href="{{site_root}}/user/{{.}}" title="@{{.}}'s profile">
|
||||
<img class="media-object avatar" src="{{#avatar}}{{.}}{{/avatar}}{{^avatar}}/assets/img/genericPerson.png{{/avatar}}" alt="{{fullname}}">
|
||||
</a>
|
||||
<h5 class="media-heading">
|
||||
{{^threads}}
|
||||
<span class="pull-right small">
|
||||
{{^is_sponsored}}<a title="View twist details" href="{{site_root}}/twist/{{.}}/{{k}}">{{/is_sponsored}}{{time}}{{^is_sponsored}}</a>{{/is_sponsored}}
|
||||
</span>
|
||||
{{/threads}}
|
||||
{{#rt_username}}
|
||||
<small>
|
||||
<a href="{{site_root}}/user/{{.}}" title="@{{.}}'s profile">@{{.}}</a>
|
||||
<span class="glyphicon glyphicon-retweet"></span>
|
||||
</small>
|
||||
{{/rt_username}}
|
||||
<a href="{{site_root}}/user/{{username}}" title="@{{username}}'s profile"><strong>@{{username}}</strong></a>
|
||||
{{^is_twist}}{{#reply}}
|
||||
<small>
|
||||
<span class="glyphicon glyphicon-share-alt"></span>
|
||||
<a title="Re: @{{username}}'s twist" href="{{site_root}}/twist/{{username}}/{{k}}">@{{username}}</a>
|
||||
</small>
|
||||
{{/reply}}{{/is_twist}}
|
||||
</h5>
|
||||
{{/username}}
|
||||
{{^username}}
|
||||
<a class="pull-left thumbnail" href="#">
|
||||
<img class="media-object avatar" src="{{site_root}}/assets/img/twister-64.jpg" alt="{{fullname}}">
|
||||
</a>
|
||||
<h5 class="media-heading">
|
||||
<span class="pull-right small">{{time}}</span>
|
||||
<a href="{{site_root}}/">@{{username}}</a>
|
||||
</h5>
|
||||
{{/username}}
|
||||
{{/user}}
|
||||
<div class="media-body">
|
||||
{{#user}}
|
||||
{{#username}}
|
||||
<h5 class="media-heading">
|
||||
<span class="pull-right small">
|
||||
<a title="View twist details" href="{{site_root}}/twist/{{.}}/{{k}}">{{time}}</a>
|
||||
</span>
|
||||
{{#rt_user}}
|
||||
<small>
|
||||
<a href="{{site_root}}/user/{{username}}" title="@{{username}}'s profile">{{fullname}}</a>
|
||||
<span class="glyphicon glyphicon-retweet"></span>
|
||||
</small>
|
||||
{{/rt_user}}
|
||||
<a href="{{site_root}}/user/{{.}}" title="@{{.}}'s profile"><strong>{{fullname}}</strong></a>
|
||||
{{^is_twist}}{{#reply}}
|
||||
<small>
|
||||
<span class="glyphicon glyphicon-share-alt"></span>
|
||||
{{#user}}<a title="Re: @{{username}}'s twist" href="{{site_root}}/twist/{{username}}/{{k}}">{{fullname}}</a>{{/user}}
|
||||
</small>
|
||||
{{/reply}}{{/is_twist}}
|
||||
</h5>
|
||||
{{/username}}
|
||||
{{^username}}
|
||||
<h5 class="media-heading">
|
||||
<span class="pull-right small">{{time}}</span>
|
||||
<a href="{{site_root}}/">{{fullname}}</a>
|
||||
</h5>
|
||||
{{/username}}
|
||||
{{/user}}
|
||||
{{{message}}}
|
||||
</div>
|
||||
</li>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html language="{{lang}}">
|
||||
<html language="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@ -22,22 +22,18 @@
|
||||
<img class="media-object avatar" src="{{#avatar}}{{.}}{{/avatar}}{{^avatar}}/assets/img/twister-64.jpg{{/avatar}}" alt="{{fullname}}">
|
||||
</a>
|
||||
<div class="media-body">
|
||||
<h4 class="media-heading">
|
||||
<a href="{{site_root}}/messages/{{username}}{{#remoteuser}}/{{username}}{{/remoteuser}}"
|
||||
<h3 class="media-heading">
|
||||
<a class="label label-primary" href="{{site_root}}/messages/{{username}}{{#remoteuser}}/{{username}}{{/remoteuser}}"
|
||||
title="@{{username}}'s messages{{#remoteuser}} with {{username}}{{/remoteuser}}"
|
||||
><span class="glyphicon glyphicon-envelope"></span></a>
|
||||
><span class="glyphicon glyphicon-envelope"></span>
|
||||
{{fullname}}'s direct messages
|
||||
{{#remoteuser}}with {{fullname}}{{/remoteuser}}
|
||||
{{#remoteuser}}with {{fullname}}{{/remoteuser}}</a>
|
||||
</h3>
|
||||
<h4>
|
||||
<a class="label label-primary" href="{{site_root}}/home/{{username}}" title="@{{username}}'s home"><span class="glyphicon glyphicon-home"></span> Home</a>
|
||||
<a class="label label-primary" href="{{site_root}}/home/{{username}}/mentions" title="mentions of @{{username}}"><span class="glyphicon glyphicon-bell"></span> Mentions</a>
|
||||
<a class="label label-info" href="{{site_root}}/user/{{username}}" title="@{{username}}'s profile"><span class="glyphicon glyphicon-user"></span> Profile</a>
|
||||
</h4>
|
||||
{{#remoteuser}}
|
||||
{{#subject}}
|
||||
<a href="{{site_root}}/messages/{{username}}" title="Back to @{{username}}'s direct message summary"><span
|
||||
class="glyphicon glyphicon-arrow-left"></span></a>
|
||||
{{/subject}}
|
||||
{{/remoteuser}}
|
||||
<a href="{{site_root}}/home/{{username}}" title="@{{username}}'s home"><span class="glyphicon glyphicon-home"></span></a>
|
||||
<a href="{{site_root}}/home/{{username}}/mentions" title="mentions of @{{username}}"><span class="glyphicon glyphicon-bell"></span></a>
|
||||
<a href="{{site_root}}/user/{{username}}" title="@{{username}}'s profile"><span class="glyphicon glyphicon-user"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
{{/subject}}
|
||||
@ -49,21 +45,13 @@
|
||||
<ul class="list-group media-list">
|
||||
{{#threads}}
|
||||
{{^remoteuser}}
|
||||
{{#user}}
|
||||
<div class="label label-info">
|
||||
<a href="{{site_root}}/messages/{{subject.username}}/{{username}}" title="See more messages to/from @{{username}}">{{fullname}}</a>
|
||||
<a href="{{site_root}}/messages/{{subject.username}}/{{username}}" title="See more messages to/from @{{username}}"><span
|
||||
class="glyphicon glyphicon-arrow-right"></span></a>
|
||||
</div>
|
||||
{{/user}}
|
||||
<a class="label label-primary" href="{{site_root}}/messages/{{subject.username}}/{{username}}"
|
||||
title="See more messages to/from @{{username}}">@{{username}} <span class="glyphicon glyphicon-arrow-right"></span></a>
|
||||
{{/remoteuser}}
|
||||
{{#remoteuser}}
|
||||
{{#subject}}
|
||||
<div class="label label-info">
|
||||
<a href="{{site_root}}/messages/{{subject.username}}" title="Back to @{{username}}'s direct message summary"><span
|
||||
class="glyphicon glyphicon-arrow-left"></span></a>
|
||||
<a href="{{site_root}}/messages/{{subject.username}}" title="Back to @{{username}}'s direct message summary">Back</a>
|
||||
</div>
|
||||
<a class="label label-primary" href="{{site_root}}/messages/{{subject.username}}"
|
||||
title="Back to @{{username}}'s direct message summary"><span class="glyphicon glyphicon-arrow-left"></span> Back</a>
|
||||
{{/subject}}
|
||||
{{/remoteuser}}
|
||||
<ul class="list-group media-list">
|
||||
|
@ -1,9 +1,9 @@
|
||||
<div class="panel panel-primary">
|
||||
<div id="localusers" class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
{{#info}}
|
||||
<div class="pull-right badge">Peers: {{dht_nodes}}/{{dht_global_nodes}}</div>
|
||||
{{/info}}
|
||||
<h3 class="panel-title"><span class="glyphicon glyphicon-home"></span> Local users</h3>
|
||||
<h3 class="panel-title"><span class="glyphicon glyphicon-th-list"></span> Local users</h3>
|
||||
</div>
|
||||
<ul class="panel-body list-group media-list">
|
||||
{{#local_users}}
|
||||
@ -18,17 +18,15 @@
|
||||
href="{{site_root}}/{{#username}}home/{{.}}{{/username}}">{{/active}}{{fullname}}{{^active}}</a>
|
||||
{{/active}}
|
||||
</h5>
|
||||
{{^active}}
|
||||
{{#username}}
|
||||
<a href="{{site_root}}/home/{{.}}" title="@{{.}}'s home"><span class="glyphicon glyphicon-home"></span></a>
|
||||
<a href="{{site_root}}/home/{{.}}/mentions" title="mentions of @{{.}}"><span class="glyphicon glyphicon-bell"></span></a>
|
||||
<a href="{{site_root}}/messages/{{.}}" title="direct messages from/to @{{.}}"><span class="glyphicon glyphicon-envelope"></span></a>
|
||||
<a href="{{site_root}}/user/{{.}}" title="@{{.}}'s profile"><span class="glyphicon glyphicon-user"></span></a>
|
||||
<a class="label label-primary" href="{{site_root}}/home/{{.}}" title="@{{.}}'s home"><span class="glyphicon glyphicon-home"></span></a>
|
||||
<a class="label label-primary" href="{{site_root}}/home/{{.}}/mentions" title="mentions of @{{.}}"><span class="glyphicon glyphicon-bell"></span></a>
|
||||
<a class="label label-primary" href="{{site_root}}/messages/{{.}}" title="direct messages from/to @{{.}}"><span class="glyphicon glyphicon-envelope"></span></a>
|
||||
<a class="label label-info" href="{{site_root}}/user/{{.}}" title="@{{.}}'s profile"><span class="glyphicon glyphicon-user"></span></a>
|
||||
{{/username}}
|
||||
{{^username}}
|
||||
(view sponsored posts)
|
||||
{{/username}}
|
||||
{{/active}}
|
||||
</div>
|
||||
</li>
|
||||
{{/local_users}}
|
||||
@ -37,27 +35,16 @@
|
||||
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<form method=get action="{{here}}" class="inline-form" role="search">
|
||||
<form target="searchresult" tag="searchresult" method=get action="{{site_root}}/search" class="inline-form" role="search">
|
||||
<div class="form-group">
|
||||
<label for="#search"><span class="glyphicon glyphicon-search"></span> Search for tag or partial username</label>
|
||||
<input id="q" name="q" type="text" class="form-control" placeholder="#twister or @twi"{{#user_prefix}} value="{{.}}"{{/user_prefix}}>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{{#user_prefix}}
|
||||
<div class="label label-primary"><span class="glyphicon glyphicon-tags"></span> User prefix search: <strong><em>{{user_prefix}}</em></strong></div>
|
||||
<ul class="list-group">
|
||||
{{#users}}<li class="list-group-item"><a href="{{site_root}}/user/{{.}}" title="@{{.}}'s profile">@{{.}}</a></li>{{/users}}
|
||||
{{^users}}<li class="list-group-item"><h3><small>Nothing. Nada. Rien de rien. 😭</small></h3>{{/users}}
|
||||
</ul>
|
||||
{{/user_prefix}}
|
||||
{{^user_prefix}}
|
||||
<div class="label label-primary"><span class="glyphicon glyphicon-tags"></span> Trending tags</div>
|
||||
<ul class="list-group">
|
||||
{{#trending}}<li class="list-group-item">{{{.}}}</li>{{/trending}}
|
||||
{{^trending}}<li class="list-group-item"><h3>Can't find trending tags. <small>Nothing. Nada. Rien de rien. 😭</small></h3>{{/trending}}
|
||||
</ul>
|
||||
{{/user_prefix}}
|
||||
</div>
|
||||
</div>
|
||||
<iframe name="searchresult" class="thumbnail media-object {{#fromMe}}pull-right{{/fromMe}}{{^fromMe}}pull-left{{/fromMe}}"
|
||||
style="width:100%; border:none; padding:0; background:none; overflow:hidden"
|
||||
width=100 height=2645 seamless=seamless
|
||||
src="{{site_root}}/search"></iframe>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html language="{{lang}}">
|
||||
<html language="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@ -24,34 +24,40 @@
|
||||
<div class="media-body">
|
||||
{{#is_home}}
|
||||
{{#username}}
|
||||
<h4 class="media-heading">
|
||||
<h3 class="media-heading">
|
||||
{{#is_feed}}
|
||||
<a href="{{site_root}}/home/{{username}}" title="@{{username}}'s home"><span class="glyphicon glyphicon-home"></span></a> {{fullname}}
|
||||
<a class="label label-primary" href="{{site_root}}/home/{{username}}" title="@{{username}}'s home"><span class="glyphicon glyphicon-home"></span>
|
||||
{{fullname}}'s home</a>
|
||||
{{/is_feed}}
|
||||
{{#is_mentions}}
|
||||
<a href="{{site_root}}/home/{{username}}/mentions" title="mentions of @{{username}}"><span class="glyphicon glyphicon-bell"></span></a> {{fullname}}
|
||||
<a class="label label-primary" href="{{site_root}}/home/{{username}}/mentions" title="mentions of @{{username}}"><span class="glyphicon glyphicon-bell"></span>
|
||||
Mentions of {{fullname}}</a>
|
||||
{{/is_mentions}}
|
||||
{{#is_messages}}
|
||||
<a href="{{site_root}}/messages/{{username}}" title="direct messages to/from @{{username}}"><span class="glyphicon glyphicon-envelope"></span></a> {{fullname}}
|
||||
<a class="label label-primary" href="{{site_root}}/messages/{{username}}" title="direct messages to/from @{{username}}"><span class="glyphicon glyphicon-envelope"></span>
|
||||
{{fullname}}</a>
|
||||
{{/is_messages}}
|
||||
</h3>
|
||||
<h4>
|
||||
{{^is_feed}}
|
||||
<a class="label label-primary" href="{{site_root}}/home/{{username}}" title="@{{username}}'s home"><span class="glyphicon glyphicon-home"></span>Home</a>
|
||||
{{/is_feed}}
|
||||
{{^is_mentions}}
|
||||
<a class="label label-primary" href="{{site_root}}/home/{{username}}/mentions" title="mentions of @{{username}}"><span class="glyphicon glyphicon-bell"></span>Mentions</a>
|
||||
{{/is_mentions}}
|
||||
{{^is_messages}}
|
||||
<a class="label label-primary" href="{{site_root}}/messages/{{username}}" title="direct messages from/to @{{username}}"><span class="glyphicon glyphicon-envelope"></span>Messages</a>
|
||||
{{/is_messages}}
|
||||
<a class="label label-info" href="{{site_root}}{{#username}}/user/{{.}}{{/username}}" title="@{{username}}'s profile"><span class="glyphicon glyphicon-user"></span>Profile</a>
|
||||
</h4>
|
||||
{{^is_feed}}
|
||||
<a href="{{site_root}}/home/{{username}}" title="@{{username}}'s home"><span class="glyphicon glyphicon-home"></span></a>
|
||||
{{/is_feed}}
|
||||
{{^is_mentions}}
|
||||
<a href="{{site_root}}/home/{{username}}/mentions" title="mentions of @{{username}}"><span class="glyphicon glyphicon-bell"></span></a>
|
||||
{{/is_mentions}}
|
||||
{{^is_messages}}
|
||||
<a href="{{site_root}}/messages/{{username}}" title="direct messages from/to @{{username}}"><span class="glyphicon glyphicon-envelope"></span></a>
|
||||
{{/is_messages}}
|
||||
<a href="{{site_root}}/user/{{username}}" title="@{{username}}'s profile"><span class="glyphicon glyphicon-user"></span></a>
|
||||
{{/username}}
|
||||
{{/is_home}}
|
||||
{{#is_user}}
|
||||
<h4 class="media-heading">
|
||||
{{#location}}<span class="pull-right small">{{.}}</span>{{/location}}
|
||||
{{fullname}}
|
||||
{{#url}}<small><a href="{{.}}">{{.}}</a></small>{{/url}}</h4>
|
||||
<a class="label label-primary" href="{{site_root}}/user/{{username}}"><span class="glyphicon glyphicon-user"></span>
|
||||
{{fullname}}</a>
|
||||
{{#url}}<small><a target="_blank" href="{{.}}">{{.}}</a></small>{{/url}}</h4>
|
||||
{{{bio}}}
|
||||
{{/is_user}}
|
||||
{{#is_tag}}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html language="{{lang}}">
|
||||
<html language="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
@ -28,14 +28,12 @@
|
||||
{{#any_rts}}
|
||||
<div class="avatars32">
|
||||
<h5 class="pull-left"><span class="glyphicon glyphicon-retweet"></span> Retwists: </h5>{{! I know it's ugly. I suck at CSS !}}
|
||||
{{#rts}}{{#rt_user}}
|
||||
<div class="thumbnail pull-left">
|
||||
<a href="{{site_root}}/user/{{username}}" title="Retwisted by {{fullname}} (@{{username}})">
|
||||
<img class="media-object avatar" src="{{#avatar}}{{.}}{{/avatar}}{{^avatar}}/assets/img/genericPerson.png{{/avatar}}"
|
||||
alt="Retwisted by {{fullname}} (@{{username}})">
|
||||
</a>
|
||||
</div>
|
||||
{{/rt_user}}{{/rts}}
|
||||
{{#rts}}
|
||||
<iframe class="thumbnail pull-left"
|
||||
style="border:none; padding:0; background:none; overflow:hidden"
|
||||
width=84 height=72 seamless=seamless
|
||||
src="{{site_root}}/user_embed/{{rt_username}}/rt"></iframe>
|
||||
{{/rts}}
|
||||
</div>
|
||||
{{/any_rts}}
|
||||
{{/twist}}
|
||||
|
15
twister.py
15
twister.py
@ -18,7 +18,7 @@ class Twister:
|
||||
db.shelve.sync()
|
||||
def _format_reply(self,r):
|
||||
"gracefully fails if reply is empty"
|
||||
return r and {"user":self.get_user_info(r['n']),'k':r['k']} or {}
|
||||
return r and {"user":self.get_user_info(r['n']),'username':r['n'],'k':r['k']} or {}
|
||||
def _format_post_info(self,p):
|
||||
result = {
|
||||
"height":p['userpost']['height'],
|
||||
@ -28,15 +28,18 @@ class Twister:
|
||||
if p['userpost'].has_key('rt'):
|
||||
result.update({
|
||||
"message":self._format_message(p['userpost']['rt']['msg']),
|
||||
"user":self.get_user_info(p['userpost']['rt']['n']),
|
||||
"username":p['userpost']['rt']['n'],
|
||||
#"user":self.get_user_info(p['userpost']['rt']['n']), ### too heavy. we do it in an iframe
|
||||
"k":p['userpost']['rt']['k'],
|
||||
"rt_user":self.get_user_info(p['userpost']['n']),
|
||||
"rt_username":p['userpost']['n'],
|
||||
#"rt_user":self.get_user_info(p['userpost']['n']), ### too heavy. we do it in an iframe
|
||||
"reply":self._format_reply(p['userpost']['rt'].get('reply',{})),
|
||||
})
|
||||
else:
|
||||
result.update({
|
||||
"message":self._format_message(p['userpost']['msg']),
|
||||
"user":self.get_user_info(p['userpost']['n']),
|
||||
"username":p['userpost']['n'],
|
||||
#"user":self.get_user_info(p['userpost']['n']), ### too heavy. we do it in an iframe
|
||||
"k":p['userpost']['k'],
|
||||
"reply":self._format_reply(p['userpost'].get('reply',{})),
|
||||
})
|
||||
@ -47,6 +50,7 @@ class Twister:
|
||||
if p:
|
||||
return self._format_post_info(p[0]['p']['v'])
|
||||
raise SkipCache("Twist not found @{0}/{1}".format(username,k),{
|
||||
"username":"",
|
||||
"user":self.get_user_info('nobody'),
|
||||
"k":0, # maybe something needs this
|
||||
"lastk":0, # or this
|
||||
@ -125,10 +129,11 @@ class Twister:
|
||||
if message['time'] > latest_ts:
|
||||
latest_ts = message['time']
|
||||
message['time'] = timestamp2iso(message['time'])
|
||||
message['username'] = message['fromMe'] and localusername or username
|
||||
message['user'] = message['fromMe'] and localuser or user
|
||||
message['message'] = self._format_message(message['text'])
|
||||
messages.insert(0,message) # reverse order (newer first)
|
||||
result.append({'user':user,'messages':messages,'latest_ts':latest_ts})
|
||||
result.append({'username':username,'user':user,'messages':messages,'latest_ts':latest_ts})
|
||||
return sorted(result,key=lambda thread:thread['latest_ts'],reverse=True)
|
||||
|
||||
@functioncache(60,ignore_instance=True)
|
||||
|
Loading…
x
Reference in New Issue
Block a user