Responsive mobile theme + public server listing.

This commit is contained in:
Beanow 2015-02-21 23:20:23 +01:00
parent 154f33ca86
commit a54e512669
7 changed files with 396 additions and 10 deletions

View File

@ -23,18 +23,27 @@ html{
font-size:100%;
}
a{
text-decoration:none;
color:inherit;
a{color:inherit;}
.mobile{
display:none !important;
}
#top-bar{
background:#f5f5f5;
padding:8px 14px;
position:fixed;
z-index:1;
top:0;
height:55px;
width:100%;
text-align:center;
position:relative;
font-weight:300;
border-bottom:1px solid #ddd;
}
#top-bar-spacer{
width:100%;
height:55px;
}
#top-bar .header{
@ -75,7 +84,6 @@ nav#links a{
background:#eee;
line-height:45px;
height:45px;
border-top:1px solid #ddd;
border-bottom:1px solid #ddd;
}
.sub-menu-outer .sub-menu-inner{
@ -124,6 +132,16 @@ nav#links a{
margin-top:3em;
}
nav#links a,
.profiles a{
text-decoration:none;
}
.search-results .intro{
text-align:justify;
}
.site,
.profile{
display:table;
width:100%;
@ -131,6 +149,13 @@ nav#links a{
color:#000;
padding:2px;
outline:none;
margin:10px 0;
}
.site{
padding:14px 2px;
margin:20px 0;
border-bottom:1px dashed #ccc;
}
.profile.selected,
@ -140,29 +165,39 @@ nav#links a{
border:1px solid #ccc;
}
.site .site-info,
.site .site-supports,
.profile .profile-photo,
.profile .profile-info{
display:table-cell;
vertical-align:top;
text-align:left;
}
.site .site-supports{
text-align:right;
padding:8px;
}
.profile .profile-photo{
margin:8px;
border-radius:15px;
border:1px solid #ddd;
}
.site .site-info,
.profile .profile-info{
padding:8px;
width:100%;
}
.site .site-info strong,
.profile .profile-info strong{
font-weight:600;
}
.site .site-info .fa,
.profile .profile-info .fa{
line-height:1.1em;
color:#999;
}
.site .site-info .url,
.profile .profile-info .url{
font-size:80%;
margin-bottom:3px;
@ -218,3 +253,152 @@ nav#links a{
width:65px;
border-radius:0 8px 8px 0;
}
.health{font-size:120%; vertical-align:bottom;}
.health.very-bad{ color:#f99; }
.health.bad{ color:#f1ba7a; }
.health.neutral{ color:#e6e782; }
.health.ok{ color:#bef273; }
.health.good{ color:#7cf273; }
.health.perfect{ color:#33ff80; }
.btn{
border:1px solid #ddd;
color:#555;
background:#eee;
border-radius:8px 8px;
height:36px;
line-height:34px;
min-width:80px;
padding:0 10px;
text-decoration:none;
display:inline-block;
}
/* smaller than tablet in portrait */
@media screen and (max-width: 880px){
body{
overflow-x:hidden;
}
.mobile{
display:inherit !important;
}
#top-bar .header{
overflow:hidden;
width:0px;
padding-left:28px;
height:28px;
background-size:28px;
}
#top-bar .search-form{
display:block;
width:100%;
padding:0 35px;
margin:0;
}
.homepage-wrapper,
.search-wrapper{
width:95%;
max-width:500px;
}
.homepage-wrapper .search-wrapper{
width:100%;
}
.homepage-wrapper{
margin:90px auto;
}
.search-results,
.sub-menu-outer .sub-menu-inner{
width:95%;
max-width:500px;
}
.hamburger{
position:absolute;
top:0px;
right:0px;
padding:14px;
font-size:22px;
line-height:22px;
cursor:pointer;
}
nav#links{
position:absolute;
width:100%;
top:54px;
right:0;
padding-bottom:5px;
}
nav#links .viewport{
position:absolute;
z-index:1;
left:100%;
width:100%;
transition:left ease 200ms;
background:#fff;
padding:20px 0;
box-shadow:1px 3px 3px rgba(0,0,0,0.2);
font-size:150%;
text-align:center;
}
nav#links.open .viewport{
left:0%;
}
#top-bar nav#links .viewport{
background:#f5f5f5;
}
nav#links h3{
margin:0;
display:block;
line-height:2em;
}
nav#links a{
display:block;
line-height:2.5em;
margin:4px 0;
}
.profile,
.profile .profile-info{
overflow-wrap:break-word;
word-wrap:break-word;
overflow:hidden;
}
}
/* The moment the header starts getting squashed */
@media screen and (max-width: 520px){
.homepage-wrapper{
margin:30px auto;
}
.homepage-wrapper .header{
font-size:40px;
background-size:36px;
display:inline-block;
margin-left:18px;
width:275px;
}
}
/* close to mobile in portrait */
@media screen and (max-width: 400px){
.profile .profile-photo{
width:60px;
border-radius:11.25px;
margin:8px 4px;
}
.profile .profile-info .url{
display:none;
}
}

126
mod/servers.php Normal file
View File

@ -0,0 +1,126 @@
<?php
use Friendica\Directory\Rendering\View;
require_once('include/site-health.php');
function servers_content(&$a) {
$sites = array();
//Find the user count per site.
$r = q("SELECT `homepage` FROM `profile`");
if(count($r)) {
foreach($r as $rr) {
$site = parse_site_from_url($rr['homepage']);
if($site) {
if(!isset($sites[$site]))
$sites[$site] = 0;
$sites[$site] ++;
}
}
}
//See if we have a health for them AND they provide SSL.
$sites_with_health = array();
$site_healths = array();
$r = q("SELECT * FROM `site-health` WHERE `reg_policy`='REGISTER_OPEN' AND `ssl_state` = 1");
if(count($r)) {
foreach($r as $rr) {
$sites_with_health[$rr['base_url']] = (($sites[$rr['base_url']] / 100) + 10) * intval($rr['health_score']);
$site_healths[$rr['base_url']] = $rr;
}
}
arsort($sites_with_health);
$total = 0;
$public_sites = array();
foreach($sites_with_health as $k => $v)
{
//Stop at unhealthy sites.
$site = $site_healths[$k];
if($site['health_score'] <= 20) break;
//Skip small sites.
$users = $sites[$k];
if($users < 5) continue;
//Add health score name and user count.
$site['health_score_name'] = health_score_to_name($site['health_score']);
$site['users'] = $users;
//Figure out what this server supports.
$plugins = explode("\r\n", $site['plugins']);
$site['plugins'] = $plugins;
$hasPlugin = function(array $input)use($plugins){
return !!count(array_intersect($input, $plugins));
};
$site['supports'] = array(
'HTTPS' => $site['ssl_state'] == 1,
'Twitter' => $hasPlugin(array('buffer', 'twitter')),
'Facebook' => $hasPlugin(array('buffer', 'facebook', 'fbpost', 'fbsync')),
'Google+' => $hasPlugin(array('buffer', 'gpluspost')),
'RSS/Atom' => true, //Built-in.
'App.net' => $hasPlugin(array('appnet', 'appnetpost')),
'Diaspora*' => $hasPlugin(array('diaspora')),
'pump.io' => $hasPlugin(array('pumpio')),
'StatusNet' => $hasPlugin(array('statusnet')),
'Tumblr' => $hasPlugin(array('tumblr')),
'Blogger' => $hasPlugin(array('blogger')),
'Dreamwidth' => $hasPlugin(array('dwpost')),
'Wordpress' => $hasPlugin(array('wppost')),
'LiveJournal' => $hasPlugin(array('ljpost')),
'Insanejournal' => $hasPlugin(array('ijpost')),
'Libertree' => $hasPlugin(array('libertree'))
);
//Subset of the full support list, to show popular items.
$site['popular_supports'] = array(
'HTTPS' => $site['supports']['HTTPS'],
'Twitter' => $site['supports']['Twitter'],
'Facebook' => $site['supports']['Facebook'],
'Google+' => $site['supports']['Google+'],
'Wordpress' => $site['supports']['Wordpress']
);
//For practical usage.
$site['less_popular_supports'] = array_diff_assoc($site['supports'], $site['popular_supports']);
//Get the difference.
$site['supports_more'] = 0;
foreach ($site['supports'] as $key => $value){
if($value && !array_key_exists($key, $site['popular_supports'])){
$site['supports_more']++;
}
}
//Push to results.
$public_sites[] = $site;
//Count the result.
$total ++;
}
//In case we asked for a surprise, pick a random one from the top 10! :D
if($a->argv[1] == 'surprise'){
$max = min(count($public_sites), 10);
$i = mt_rand(0, $max-1);
$surpriseSite = $public_sites[$i];
header('Location:'.$surpriseSite['base_url'].'/register');
exit;
}
//Show results.
$view = new View('servers');
$view->output(array(
'total' => number_format($total),
'sites' => $public_sites
));
}

View File

@ -1,4 +1,16 @@
<a class="hamburger mobile"><i class="fa fa-bars"></i></a>
<nav id="links">
<a href="/stats">Stats</a>
<a href="/help">Help</a>
</nav>
<div class="viewport">
<a href="/home" class="mobile">Home</a>
<a href="/servers">Servers</a>
<a href="/stats">Stats</a>
<a href="/help">Help</a>
</div>
</nav>
<script type="text/javascript">
jQuery('.hamburger').on('click', function(e){
e.preventDefault();
jQuery('nav#links').toggleClass('open');
})
</script>

View File

@ -10,4 +10,5 @@
<?php echo $this->layout('_navigation'); ?>
</header>
</header>
<div id="top-bar-spacer"></div>

View File

@ -2,7 +2,7 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1">
<link rel="search" type="application/opensearchdescription+xml" title="Friendica Directory" href="/opensearch" />
<title>Friendica Directory</title>
@ -12,6 +12,8 @@
<link href="//fonts.googleapis.com/css?family=Lato:100,300" rel="stylesheet" type="text/css">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<link href="/assets/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="//code.jquery.com/jquery-1.11.2.min.js"></script>
</head>
<body>
<?php if(isset($topBar)) echo $topBar; ?>

View File

@ -0,0 +1,37 @@
<div class="site">
<div class="site-info">
<strong class="name">
<span class="health <?php echo $site['health_score_name']; ?>"
title="Health: <?php echo $site['health_score_name']; ?>">&hearts;</span>
<?php echo $site['name']; ?>
</strong>
<div class="url">
<?php if ($site['supports']['HTTPS']): ?>
<i class="fa fa-lock"></i>&nbsp;
<?php endif ?>
<a href="<?php echo $site['base_url']; ?>"><?php echo $site['base_url']; ?></a>
</div>
<div class="section">
<span class="users"><?php echo $site['users']; ?> users</span>,
<span class="admin">admin: <a href="<?php echo $site['admin_profile']; ?>"><?php echo $site['admin_name']; ?></a></span>
</div>
<p class="description"><?php echo $site['info']; ?></p>
</div>
<div class="site-supports">
<em>Features</em>
<?php foreach ($site['popular_supports'] as $key => $value): if(!$value) continue; ?>
<div class="supports <?php echo strtolower($key); ?>"><?php echo $key; ?>&nbsp;&nbsp;&radic;</div>
<?php endforeach ?>
<?php if ($site['supports_more'] > 0): ?>
<?php
$more = '';
foreach ($site['less_popular_supports'] as $key => $value){
if(!$value) continue;
$more .= $key.PHP_EOL;
}
?>
<abbr class="more" title="<?php echo $more ?>">+<?php echo $site['supports_more']; ?> more</abbr>
<?php endif ?>
</div>
</div>

View File

@ -0,0 +1,24 @@
<div class="search-results">
<div class="sites">
<h1>Public servers</h1>
<p class="intro">
If you are not interested in <a href="http://friendica.com/download">hosting your own server</a>, you can still use Friendica.
Here are some public server run by enthousiasts that you can join.
We recommend these based on their <abbr title="Decent speed, proper security, recent version, etc.">health</abbr>.
</p>
<p class="intro">
Keep in mind that different servers may support different networks besides Friendica.
It's best to pick the one that best suits your needs.
</p>
<div class="feeling-lucky">
<a class="btn surprise" href="/servers/surprise">Surprise me &raquo;</a>
</div>
<h3>Recommending <?php echo $total; ?> public servers</h3>
<?php
foreach ($sites as $site)
echo $this->view('_site', array('site'=>$site));
?>
</div>
</div>