Browse files

added first support for mobile browser handling

  • Loading branch information...
1 parent 9489649 commit 4813929ab84724c231ecdc9a89ef61d05a1d092e @polettix committed Sep 27, 2012
View
100 lib/Narsil/Frontend.pm
@@ -8,18 +8,29 @@ use URI;
use Try::Tiny;
use Storable qw< dclone >;
+my %layout_name_for = (
+ normal => 'main',
+ mobile => 'mobile',
+);
+
BEGIN {
+ unshift @INC, qw< /home/poletti/sviluppo/perl/narsil/core/lib >;
+ #die if exists $ENV{DOTCLOUD_ENVIRONMENT};
unshift @INC, qw< /home/poletti/sviluppo/perl/narsil/core/lib >
- unless exists $ENV{DOTCLOUD_ENVIRONMENT};
+ unless exists $ENV{DOTCLOUD_ENVIRONMENT};
}
use Narsil::Authentication;
setup_authentication(
authentication_callback => \&authenticate,
- (exists($ENV{DOTCLOUD_ENVIRONMENT}) ? () : (authorization_callback =>
- sub {
- session('user') || session(user => {username => 'polettix'})
- })),
+ (
+ exists($ENV{DOTCLOUD_ENVIRONMENT}) ? () : (
+ authorization_callback => sub {
+ warning "\n\n\n\n in authorization callback \n\n\n\n";
+ session('user') || session(user => {username => 'polettix'});
+ }
+ )
+ ),
);
sub user { return session('user') }
@@ -52,7 +63,7 @@ sub rest_call {
$retval = decode_json($response->content());
}
catch {
- $retval = { error => $_ };
+ $retval = {error => $_};
};
return $retval;
} ## end sub rest_call
@@ -75,22 +86,44 @@ sub authenticate {
return;
} ## end sub authenticate
+{
+ my $template_sub = \&template;
+ no strict 'refs';
+ no warnings 'redefine';
+ *{'template'} = sub {
+ push @_, {} while @_ < 3;
+ $_[2]->{layout} = session('layout') // 'mobile'
+ unless exists($_[2]->{layout});
+ my $layout = $_[2]->{layout};
+
+ my $te = engine 'template';
+ my $candidate = "$layout/$_[0]";
+ my $path = $te->view($candidate);
+ warning "candidate: $candidate";
+ warning "path: " . ($path // 'undef');
+ splice @_, 0, 1, $candidate if defined($path) && -r $path;
+
+ goto $template_sub;
+ };
+}
+
+
hook before_template => sub {
my $tokens = shift;
- $tokens->{development} = ! exists $ENV{DOTCLOUD_ENVIRONMENT};
+ $tokens->{development} = !exists $ENV{DOTCLOUD_ENVIRONMENT};
};
get '/' => sub {
- my $matches = get_matches_for(user(), 'active');
+ my $matches = get_matches_for(user(), 'active');
my ($waiting, $availables) = get_gathering_matches(user());
- my $games = get_games();
- my $users = get_users();
+ my $games = get_games();
+ my $users = get_users();
return template 'index',
{
matches => $matches,
- string => to_json($matches),
availables => $availables,
waiting => $waiting,
+ string => to_json($waiting),
games => $games,
users => $users
};
@@ -109,7 +142,7 @@ sub get_games {
return rest_call(get => '/games');
}
-sub get_gathering_matches {
+sub get_gathering_matches_old {
return rest_call(get => '/matches/gathering');
}
@@ -135,43 +168,46 @@ sub get_gathering_matches {
get => "/matches/gathering",
{user => $userid,}
);
- my $matches = delete $stuff->{matches};
- my $waiting = dclone($stuff);
+ my $matches = delete $stuff->{matches};
+ my $waiting = dclone($stuff);
my $available = dclone($stuff);
for my $match (@$matches) {
($match->{id} = $match->{uri}) =~ s{.*/}{}mxs;
- if (grep {defined($userid) && ($_->[0] eq $userid)} @{$match->{participants}}) {
+ if (grep { defined($userid) && ($_->[0] eq $userid) }
+ @{$match->{participants}})
+ {
$match->{is_participant} = 1;
push @{$waiting->{matches}}, $match;
- }
+ } ## end if (grep { defined($userid...
else {
$match->{opponents} =
- [grep { !(defined($userid) && ($_->[0] eq $userid)) } @{$match->{participants}}];
+ [grep { !(defined($userid) && ($_->[0] eq $userid)) }
+ @{$match->{participants}}];
$match->{is_participant} = 0;
push @{$available->{matches}}, $match;
- }
- }
+ } ## end else [ if (grep { defined($userid...
+ } ## end for my $match (@$matches)
return ($waiting, $available);
-} ## end sub get_available_matches
+} ## end sub get_gathering_matches
sub get_matches_for {
my ($user, $phase) = @_;
return {} unless defined $user;
my $userid = $user->{username};
$phase //= 'active';
- my $stuff = rest_call(
+ my $stuff = rest_call(
get => "/user/matches/$userid",
{
phase => $phase,
- user => $userid,
+ user => $userid,
}
);
for my $match (@{$stuff->{matches}}) {
($match->{id} = $match->{uri}) =~ s{.*/}{}mxs;
$match->{opponents} =
[grep { $_->[0] ne $userid } @{$match->{participants}}];
$match->{movers} = [map { $_->[0] } @{$match->{movers}}];
- }
+ } ## end for my $match (@{$stuff...
return $stuff;
} ## end sub get_matches_for
@@ -193,7 +229,7 @@ get '/match/:id' => sub {
catch {
warning $_;
};
- template $template => {string => to_json($match), %$match};
+ template match => {string => to_json($match), subtemplate => $template , %$match};
};
post '/match' => sub {
@@ -212,7 +248,7 @@ post '/match' => sub {
catch {
warning "caught error during forward: $_";
};
- return redirect request.uri_for('/');
+ return redirect request . uri_for('/');
};
post '/match/joins/:id' => sub {
@@ -273,13 +309,15 @@ get '/game/:id' => sub {
};
get '/games' => sub {
- my $games = get_games();
- return template 'games',
- {
- games => $games,
- };
-
+ my $games = get_games();
+ return template 'games', {games => $games,};
+
};
+post '/layout' => sub {
+ session layout => $layout_name_for{param('layout')} // 'main';
+ flash info => 'layout_set';
+ return redirect request()->referer();
+};
true;
View
236 public/css/mobile.css
@@ -0,0 +1,236 @@
+body {
+ margin: 0;
+ padding: 0.2em;
+ padding-top: 0;
+ background-color: #efe;
+ font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana";
+ color: #444;
+ width: 238px;
+ font-size: 75%;
+}
+
+h1, h2, h3, h4, h5, h6, p, a, ul, li {
+ margin: 0;
+ padding: 0.1em;
+}
+
+#header h1 {
+ font-size: 140%;
+ font-family: Monospace;
+}
+
+ul {
+ list-style-position: inside;
+ padding-left: 0.3em;
+}
+
+button.aslink {
+ border: none;
+ background: transparent;
+ padding: 0;
+ margin: 0;
+ cursor: pointer;
+ font-size: 100%;
+}
+
+a, a:visited, button.aslink {
+ color: #03c;
+ text-decoration: none;
+}
+
+a:hover, button.aslink:hover {
+ background-color: #03c;
+ color: white;
+ text-decoration: none;
+}
+
+#header, #navigation, #content-container, #content, #footer {
+ margin: 0;
+ padding: 0;
+ background-color: #777;
+}
+
+#header {
+ background-color: green;
+ color: white;
+ text-align: center;
+ padding: 0.3em;
+}
+
+#header h1 {
+ border: none;
+}
+
+#navigation {
+ background-color: lightgreen;
+ color: black;
+ padding: 0.3em;
+ height: 1.3em;
+ margin: 2px 0;
+}
+
+#navigation ul {
+ list-style: none;
+ border: none;
+ padding: 0;
+ float:left;
+}
+
+#navigation ul li {
+ display: inline;
+ border: none;
+ padding: 0 0.3em;
+}
+
+#navigation a, #navigation a:visited, #navigation button {
+ border: none;
+ color: #050;
+}
+
+#navigation a:hover, #navigation button.aslink:hover {
+ background-color: transparent;
+ color: #080;
+}
+
+#navigation form {
+ display: inline;
+}
+
+#content-container {
+ background-color: white;
+ padding: 0.3em;
+ clear: both;
+}
+
+#content {
+ background-color: white;
+}
+
+#content h2 {
+ font-size: 100%;
+ color: green;
+}
+
+#content h2.gametitle {
+ margin-bottom: 0.5em;
+}
+
+#content p, #content li {
+ font-size: 90%;
+}
+
+#footer {
+ background-color: transparent;
+ clear: both;
+ text-align: right;
+ font-size: 83%;
+ padding: 1em;
+}
+
+#footer p {
+ border: none;
+}
+
+ul#flash {
+ list-style-position: inside;
+ list-style: none;
+ background: #f55;
+ border: 5px solid red;
+ padding: 3px;
+}
+
+ul#flash li {
+ display: block;
+ font-weight: bold;
+ padding: 0.3em;
+ margin: 0.1em;
+ text-align: center;
+}
+
+ul#flash li.info {
+ background: lightgreen;
+ color: green;
+}
+
+ul#flash li.warning {
+ background: #fa3;
+ color: #730;
+}
+
+ul#flash li.error {
+ background: #faa;
+ color: #700;
+}
+
+form.logout {
+ display: inline;
+}
+form.logout button {
+ border: none;
+ background: transparent;
+ color: green;
+ font-size: 100%;
+ padding: 0;
+ margin: 0;
+ cursor: pointer;
+}
+
+table.battleboat td {
+ border: 0;
+ border: 1px solid #777;
+ padding: 2px;
+ padding: 0;
+}
+
+table.battleboat td.in-last {
+ background-color: orange;
+}
+
+table.battleboat {
+ font-family: courier;
+ border: 1px solid black;
+ border-collapse: collapse;
+ background-color: cyan;
+}
+
+#battleboat h3 {
+ color: blue;
+ font-size: 100%;
+ text-align: center;
+}
+
+#battleboat div#upper, #battleboat div#lower {
+ margin: 0.6em 0 0 0;
+ float: left;
+}
+
+form.auth {
+ text-align: center;
+}
+
+ul.matches, ul.games {
+ list-style: none;
+}
+
+div.matches h2, div.games h2 {
+ margin: 1em 0 0 0;
+}
+
+div.matches h2.first, div.games h2 {
+ margin: 0;
+}
+
+ul.layouts {
+ list-style: none;
+ display: inline;
+}
+
+ul.layouts li {
+ display: inline;
+}
+
+p.forlist {
+ display: inline;
+}
+
+form.layout { display: inline }
View
15 public/css/style.css
@@ -187,3 +187,18 @@ table.battleboat {
border-collapse: collapse;
background-color: cyan;
}
+
+ul.layouts {
+ list-style: none;
+ display: inline;
+}
+
+ul.layouts li {
+ display: inline;
+}
+
+p.forlist {
+ display: inline;
+}
+
+form.layout { display: inline }
View
2 views/_games.tt
@@ -1,4 +1,4 @@
-<ul>
+<ul class="games">
<% FOR game = games;
id = game.id;
uri = request.uri_for("/game/$id");
View
2 views/_matches.tt
@@ -1,4 +1,4 @@
-<ul>
+<ul class="matches">
<% FOR match = matches.matches;
id = match.id;
uri = request.uri_for("/match/$id");
View
8 views/games/battleship/play.tt
@@ -1,9 +1,7 @@
-<h1>Battleship</h1>
-<p><% IF active_player %>It's <% active_player %>'s turn<% ELSE %><% match.winners.0.0 %> won the match<% END %></p>
+<p><% IF active_player %><strong><% active_player | html %></strong> to move<% ELSE %><strong><% match.winners.0.0 %></strong> won the match<% END %></p>
<div id="battleboat">
<div id="upper">
-<h2><% upper %>'s field</h2>
<table class="battleboat">
<%
ofield = expanded_field.$upper;
@@ -41,10 +39,11 @@
END;
%>
</table>
+<h3><% upper %></h3>
</div>
<div id="lower">
-<h2><% lower %>'s field</h2>
+<h3><% lower %></h3>
<table class="battleboat">
<%
pfield = expanded_field.$lower;
@@ -69,5 +68,6 @@
%>
</table>
</div>
+<div style="clear:both"></div>
</div>
<!-- pre><% string %></pre -->
View
18 views/games/battleship/setup.tt
@@ -1,20 +1,8 @@
-<h1>Battleship</h1>
-
-Match is in setup phase. The following users are setting up:
-
-<ul>
-<% FOR mover = movers %>
- <li><% mover %></li>
-<% END %>
-</ul>
-
<% IF player_is_active %>
-Setup it here...
-
+<p>Setup your battle field <% lower %></p>
<div id="battleboat">
<div id="lower">
-<h2><% lower %>'s field</h2>
<%
uri = request.uri_for("/move");
%>
@@ -74,4 +62,8 @@ Setup it here...
</div>
+<% ELSE %>
+
+Waiting for <% movers.0 %> to complete setup...
+
<% END %>
View
1 views/index.tt
@@ -1,4 +1,3 @@
-<h1>Welcome to Narsil!</h1>
<h2>Active Matches</h2>
<% INCLUDE _matches.tt matches = matches %>
<h2>Waiting Matches</h2>
View
1 views/layouts/main_/flash/layout_set.tt
@@ -0,0 +1 @@
+Layout set.
View
9 views/layouts/main_/footer.tt
@@ -1 +1,10 @@
+<% MACRO layoutlink(name) BLOCK %>
+<form class="layout" method="post" action="<% request.uri_for('/layout') %>">
+ <button class="aslink" name="layout" value="<% name | html %>"><% name | html%></button>
+</form>
+<% END %>
+<p class="forlist">Style:</p><ul class="layouts">
+ <li><% layoutlink('normal') %></li>
+ <li><% layoutlink('mobile') %></li>
+</ul>
<p>Copyright (C) 2012 Flavio Poletti</p>
View
37 views/layouts/mobile.tt
@@ -0,0 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-type" content="text/html; charset=<% settings.charset %>" />
+<title>Narsil - mobile</title>
+<link rel="stylesheet" href="<% request.uri_for('/css/mobile.css') %>" />
+<link rel="shortcut icon" href="<% request.uri_for('/images/favicon.ico') %>" />
+
+</head>
+ <body>
+ <div id="container">
+ <div id="header"><% INCLUDE 'layouts/mobile_/header.tt' %></div>
+ <div id="navigation"><% INCLUDE 'layouts/mobile_/navigation.tt' %></div>
+ <div id="content-container">
+ <div id="content">
+<% IF flash %>
+ <ul id="flash">
+ <%
+ FOR report = flash;
+ class = report.0;
+ name = report.1;
+ %>
+ <li class="<% class %>"><% INCLUDE "layouts/mobile_/flash/${name}.tt" %></li>
+ <%
+ END;
+ %>
+ </ul><!-- flash -->
+<% END %>
+ <% content %>
+ </div><!-- content -->
+ <div style="clear:both"></div>
+ </div><!-- content-container -->
+ <div id="footer"><% INCLUDE 'layouts/mobile_/footer.tt' %></div>
+ </div><!-- container -->
+ </body>
+</html>
View
1 views/layouts/mobile_/flash
View
1 views/layouts/mobile_/footer.tt
View
1 views/layouts/mobile_/header.tt
View
11 views/layouts/mobile_/navigation.tt
@@ -0,0 +1,11 @@
+<ul>
+<% IF session.user %>
+ <li><strong>Hey <% session.user.username %></strong>
+ <form method="POST" action="<% request.uri_for('/logout') %>">
+ <span style="font-size: 70%">(<button class="aslink">Logout</button>)</span>
+ </form>
+ </li>
+<% END %>
+ <li><a href="<% request.base %>">Home</a></li>
+ <li><a href="<% request.uri_for("/games") %>">Games</a></li>
+</ul>
View
2 views/match.tt
@@ -0,0 +1,2 @@
+<h2 class="gametitle">Battleship</h2>
+<% INCLUDE $subtemplate %>
View
4 views/mobile/games.tt
@@ -0,0 +1,4 @@
+<h2>Available Games</h2>
+<div class="games">
+<% INCLUDE _games.tt %>
+</div>
View
25 views/mobile/index.tt
@@ -0,0 +1,25 @@
+<% IF session.user %>
+<div class="matches">
+ <% IF matches.matches.size %>
+ <h2 class="first">Active Matches</h2>
+ <% INCLUDE _matches.tt matches = matches %>
+ <% END %>
+ <% IF waiting.matches.size %>
+ <h2>Waiting Matches</h2>
+ <% INCLUDE _matches.tt matches = waiting %>
+ <% END %>
+ <% IF availables.matches.size %>
+ <h2>Available Matches</h2>
+ <% INCLUDE _matches.tt matches = availables %>
+ <% END %>
+</div>
+<% ELSE %>
+ <form class="auth" method="POST" action="<% request.uri_for('/login') %>">
+ username:<input type="text" name="username" value="" />
+ <br />
+ password:<input type="password" name="password" value="" />
+ <br />
+ <input type="hidden" name="uri" value="<% request.uri_for('/') %>">
+ <input type="submit" name="submit" value="enter" />
+ </form>
+<% END %>

0 comments on commit 4813929

Please sign in to comment.