Optimized mobile read view

This commit is contained in:
Mario Volke 2014-10-16 15:10:00 +02:00 committed by Tankred Hase
parent c9c05302d2
commit c3021a7244
9 changed files with 240 additions and 125 deletions

8
src/img/icons/dropup.svg Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-1.1 262.9 597.5 320.6" enable-background="new -1.1 262.9 597.5 320.6" xml:space="preserve">
<path d="M9.2,503.4c-13.7,9.2-13.7,27.5,0,36.6l41.2,36.6c13.7,9.2,32.1,9.2,41.2,0l206.1-174l201.5,174c13.7,9.2,32.1,9.2,41.2,0
l45.8-36.6c13.7-9.2,13.7-27.5,0-36.6L316,269.8c-13.7-9.2-32.1-9.2-41.2,0L9.2,503.4z"/>
</svg>

After

Width:  |  Height:  |  Size: 693 B

View File

@ -45,6 +45,7 @@
@import "blocks/basics/attachments";
@import "blocks/basics/tooltip";
@import "blocks/basics/dropdown";
@import "blocks/basics/toolbar";
@import "blocks/layout/app";
@import "blocks/layout/nav";
@import "blocks/layout/action-bar";

View File

@ -299,7 +299,6 @@
margin: 0;
font-size: $font-size-base;
opacity: 0.5;
transition: opacity 0.3s;
outline: 0;
&:focus,

View File

@ -45,4 +45,8 @@
}
}
}
&__stripped:after {
content: "";
}
}

View File

@ -0,0 +1,51 @@
.toolbar {
&__label {
@include scut-truncate;
display: block;
// has to be same as actions
box-sizing: content-box;
padding: 10px 15px;
line-height: 24px;
height: 24px;
font-size: $font-size-bigger;
color: $color-text;
text-decoration: none;
& > svg {
display: inline-block;
fill: $color-main;
vertical-align: baseline;
height: 0.8em;
width: 0.8em;
}
&.wo-touch-active {
background: $color-touch-active;
}
}
&__actions {
display: flex;
flex-direction: row;
text-align: center;
list-style: none;
margin: 0;
// has to be same as label
box-sizing: content-box;
padding: 10px 15px;
line-height: 24px;
height: 24px;
& > li {
flex-grow: 1;
}
@include respond-to(md) {
justify-content: flex-end;
& > li {
flex-grow: 0;
padding-left: 30px;
}
}
}
}

View File

@ -1,7 +1,7 @@
// Container for mail list entries
.mail-list {
$padding-horizontal: 15px;
$padding-vertical: 10px;
$padding-vertical: 15px;
$footer-height: 30px;
// do not share any common styles between large and other screens
@ -18,7 +18,7 @@
& > header {
position: relative;
flex-shrink: 0;
padding: $padding-horizontal ($padding-vertical + 5px);
padding: $padding-vertical $padding-horizontal;
cursor: pointer;
.btn-navicon {
@ -33,11 +33,15 @@
font-size: $font-size-bigger;
font-weight: normal;
}
.btn-icon {
.btn-icon-light {
position: absolute;
top: $padding-vertical;
right: $padding-horizontal;
margin-top: -0.05em; // for perfect vertical alignment with headline
padding-left: 1em;
& > svg {
width: 2em;
height: 2em;
}
}
&.wo-touch-active {
@ -78,18 +82,8 @@
width: 100%;
font-size: $font-size-smaller;
color: $color-text;
line-height: $footer-height - 4px;
&:before {
content: '';
display: block;
position: absolute;
top: 0;
left: $padding-horizontal;
right: $padding-horizontal;
height: 0;
border-top: 1px solid $color-grey-medium;
}
line-height: $footer-height;
border-top: 1px solid $color-border-light;
svg {
display: inline-block;
@ -107,7 +101,7 @@
h2 {
padding-right: 0;
}
.btn-icon {
.btn-icon-light {
display: none;
}
}
@ -248,8 +242,8 @@
& > svg {
display: inline-block;
vertical-align: middle;
width: 1em;
height: 1em;
width: 1.2em;
height: 1.2em;
fill: $color-main;
}
}

View File

@ -1,12 +1,33 @@
.read {
$padding-horizontal: 15px;
$padding-vertical: 10px;
display: flex;
flex-direction: column;
padding: 10px;
height: 100%;
width: 100%;
@include respond-to(lg) {
padding: 20px 20px 10px;
// Toolbars
&__folder-toolbar {
flex-shrink: 0;
border-bottom: 1px solid $color-border-light;
@include respond-to(md) {
display: none;
}
}
&__action-toolbar {
flex-shrink: 0;
order: 100; // stick to bottom on mobile
border-top: 1px solid $color-border-light;
@include respond-to(md) {
order: initial;
border-top: none;
border-bottom: 1px solid $color-border-light;
}
@include respond-to(lg) {
display: none;
}
}
// Header components
@ -14,52 +35,67 @@
&__header {
flex-shrink: 0;
margin-bottom: 1em;
padding: $padding-vertical $padding-horizontal 0;
& > .attachments {
margin-top: 1em;
}
}
&__controls,
&__controls-lg {
// only visible in stripped version of read view
.mail-addresses__stripped {
display: none;
}
&__controls {
display: none;
float: right;
margin-left: 1em;
.btn-icon {
margin-left: 0.5em;
}
.btn-icon-light {
margin-left: 1em;
}
}
&__controls {
@include respond-to(lg) {
display: none;
}
}
&__controls-lg {
display: none;
@include respond-to(lg) {
display: block;
}
}
&__subject {
font-size: $font-size-bigger;
font-weight: bold;
color: $color-text;
margin: 0 0 0.2em;
@include respond-to(not-md) {
cursor: pointer;
&.wo-touch-active {
background: $color-touch-active;
}
.btn-icon-very-light {
float: right;
margin-left: 1em;
}
@include respond-to(md) {
display: none;
}
}
&__subject-md {
display: none;
font-size: $font-size-bigger;
font-weight: normal;
margin: 0 0 0.2em;
& > svg {
display: inline-block;
display: none;
fill: $color-main;
vertical-align: baseline;
height: 0.8em;
width: 0.8em;
@include respond-to(md-only) {
display: none;
}
}
&.wo-touch-active {
background: $color-touch-active;
@include respond-to(md) {
display: block;
}
@include respond-to(lg) {
cursor: pointer;
& > svg {
display: inline-block;
}
&.wo-touch-active {
background: $color-touch-active;
}
}
}
&__time {
@ -73,17 +109,21 @@
&__signature-status {
flex-shrink: 0;
margin-top: 0;
margin-bottom: 0.5em;
text-align: center;
color: $color-error;
padding: 0 $padding-horizontal;
}
&__display-images {
flex-shrink: 0;
margin-bottom: 0.5em;
text-align: center;
padding: 0 $padding-horizontal;
}
&__working {
flex-grow: 1;
padding: 0 $padding-horizontal;
& > div {
@include scut-vcenter-tt;
width: 100%;
@ -103,6 +143,7 @@
// allow scrolling on iOS
overflow: auto;
-webkit-overflow-scrolling: touch;
padding: 0 $padding-horizontal $padding-vertical;
iframe {
flex-grow: 1;
@ -111,48 +152,6 @@
}
}
// Popovers
// TODO: refactor to BEM
.reply-selection {
.popover-content {
padding: 0;
}
ul {
list-style: none;
margin: 0;
}
li {
border-bottom: 1px solid $color-border-light;
&:last-child {
border-bottom: 0;
}
}
button {
display: block;
background: none;
width: 100%;
border: 0;
outline: 0;
padding: 0.5em 1em 0.5em 0.3em;
color: $color-main;
transition: background-color 0.3s;
text-align: left;
& > svg {
display: inline-block;
width: 2em;
height: 1em;
vertical-align: middle;
fill: $color-main;
}
&:hover,
&:focus {
background-color: darken($color-white, 2%);
}
}
}
// Modifiers
&--no-attachments {
@ -162,4 +161,17 @@
border-bottom: 1px solid $color-border-light;
}
}
@include respond-to(sm-only) {
&--stripped {
.read__addresses > * {
display: none;
&:first-child {
display: block;
}
}
.mail-addresses__stripped {
display: inline;
}
}
}
}

View File

@ -8,7 +8,7 @@
<h2>{{state.nav.currentFolder.type}}</h2>
</div>
<button class="btn-icon" title="New mail" wo-touch="state.writer.write(); $event.stopPropagation()">
<button class="btn-icon-light" title="New mail" wo-touch="state.writer.write(); $event.stopPropagation()">
<svg><use xlink:href="#icon-write" /><title>New mail</title></svg>
</button>
</header>

View File

@ -1,56 +1,102 @@
<div class="read" ng-controller="ReadCtrl"
ng-class="{'read--no-attachments': !state.mailList.selected.attachments || state.mailList.selected.attachments.length === 0}">
ng-class="{
'read--no-attachments': !state.mailList.selected.attachments || state.mailList.selected.attachments.length === 0,
'read--stripped': !notStripped
}">
<div class="read__folder-toolbar">
<div class="toolbar">
<a class="toolbar__label" href="javascript:;" wo-touch="state.read.toggle(false)">
<svg><use xlink:href="#icon-back" /><title>Back</title></svg> Folder name
</a>
</div>
</div>
<div class="read__action-toolbar">
<div class="toolbar">
<ul class="toolbar__actions">
<li>
<button class="btn-icon-light" ng-hide="true" title="Remove from favorites">
<svg><use xlink:href="#icon-star_filled" /><title>Favorited</title></svg>
</button>
<button class="btn-icon-light" title="Add to favorites">
<svg><use xlink:href="#icon-star" /><title>Favorite</title></svg>
</button>
</li>
<li>
<button class="btn-icon-light" title="Move mail">
<svg><use xlink:href="#icon-folder" /><title>Move mail</title></svg>
</button>
</li>
<li>
<button wo-touch="state.mailList.remove(state.mailList.selected)" class="btn-icon-light" title="Delete mail">
<svg><use xlink:href="#icon-trash" /><title>Delete mail</title></svg>
</button>
</li>
<li>
<button class="btn-icon-light" title="Reply to" wo-dropdown="#reply-selection" wo-dropdown-position="center">
<svg><use xlink:href="#icon-reply_light" /><title>Reply to</title></svg>
</button>
</li>
<li>
<button wo-touch="state.writer.write()" class="btn-icon-light" title="New mail">
<svg><use xlink:href="#icon-write" /><title>New mail</title></svg>
</button>
</li>
</ul>
</div>
</div>
<header class="read__header">
<div class="read__controls">
<button wo-touch="state.mailList.remove(state.mailList.selected)" class="btn-icon" title="Delete mail">
<svg><use xlink:href="#icon-delete" /><title>Delete mail</title></svg>
</button>
<button class="btn-icon" title="Reply to" wo-dropdown="#reply-selection" wo-dropdown-position="center">
<svg><use xlink:href="#icon-reply" /><title>Reply to</title></svg>
</button>
<button wo-touch="state.writer.write()" class="btn-icon" title="New mail">
<svg><use xlink:href="#icon-write" /><title>New mail</title></svg>
</button>
</div>
<div class="read__controls-lg">
<button class="btn-icon-light" wo-touch="state.writer.write(state.mailList.selected)" title="Reply"><svg><use xlink:href="#icon-reply_light" /></svg></button>
<button class="btn-icon-light" wo-touch="state.writer.write(state.mailList.selected, true)" title="Reply All"><svg><use xlink:href="#icon-reply_all_light" /></svg></button>
<button class="btn-icon-light" wo-touch="state.writer.write(state.mailList.selected, null, true)" title="Forward"><svg><use xlink:href="#icon-forward_light" /></svg></button>
</div>
<h2 class="read__subject" wo-touch="state.read.toggle(false)">
<h2 class="read__subject" wo-touch="notStripped = !notStripped">
<button ng-hide="notStripped" class="btn-icon-very-light">
<svg><use xlink:href="#icon-dropdown" /><title>More</title></svg>
</button>
<button ng-show="notStripped" class="btn-icon-very-light">
<svg><use xlink:href="#icon-dropup" /><title>Less</title></svg>
</button>
{{state.mailList.selected.subject ? state.mailList.selected.subject : 'No subject'}}
</h2>
<h2 class="read__subject-md" wo-touch="state.read.toggle(false)">
<svg><use xlink:href="#icon-back" /><title>Back</title></svg>
{{state.mailList.selected.subject ? state.mailList.selected.subject : 'No subject'}}
</h2>
<time class="read__time">{{state.mailList.selected.sentDate | date:'EEEE, MMM d, yyyy h:mm a'}}</time>
<div class="mail-addresses">
<label>From:</label>
<span ng-repeat="u in state.mailList.selected.from">
<span class="label" ng-class="{'label--invalid': u.secure === false, 'label--invalid-clickable': u.secure === false}" ng-mouseover="getKeyId(u.address)" wo-touch="invite(u)" wo-tooltip="#fingerprint-info">
{{u.name || u.address}}
<svg ng-show="u.secure === false"><use xlink:href="#icon-add_contact" /></svg>
<div class="read__addresses">
<div class="mail-addresses">
<label>From:</label>
<span ng-repeat="u in state.mailList.selected.from">
<span class="label" ng-class="{'label--invalid': u.secure === false, 'label--invalid-clickable': u.secure === false}" ng-mouseover="getKeyId(u.address)" wo-touch="invite(u)" wo-tooltip="#fingerprint-info">
{{u.name || u.address}}
<svg ng-show="u.secure === false"><use xlink:href="#icon-add_contact" /></svg>
</span>
<span class="mail-addresses__stripped"></span>
</span>
</span>
</div>
<div class="mail-addresses">
<label>To:</label>
<span ng-repeat="u in state.mailList.selected.to">
<span class="label" ng-class="{'label--invalid': u.secure === false, 'label--invalid-clickable': u.secure === false}" ng-mouseover="getKeyId(u.address)" wo-touch="invite(u)" wo-tooltip="#fingerprint-info">
{{u.name || u.address}}
<svg ng-show="u.secure === false"><use xlink:href="#icon-add_contact" /></svg>
</div>
<div class="mail-addresses">
<label>To:</label>
<span ng-repeat="u in state.mailList.selected.to">
<span class="label" ng-class="{'label--invalid': u.secure === false, 'label--invalid-clickable': u.secure === false}" ng-mouseover="getKeyId(u.address)" wo-touch="invite(u)" wo-tooltip="#fingerprint-info">
{{u.name || u.address}}
<svg ng-show="u.secure === false"><use xlink:href="#icon-add_contact" /></svg>
</span>
</span>
</span>
</div>
<div class="mail-addresses" ng-show="state.mailList.selected.cc && state.mailList.selected.cc.length > 0">
<label>Cc:</label>
<span ng-repeat="u in state.mailList.selected.cc">
<span class="label" ng-class="{'label--invalid': u.secure === false, 'label--invalid-clickable': u.secure === false}" ng-mouseover="getKeyId(u.address)" wo-touch="invite(u)" wo-tooltip="#fingerprint-info">
{{u.name || u.address}}
<svg ng-show="u.secure === false"><use xlink:href="#icon-add_contact" /></svg>
</div>
<div class="mail-addresses" ng-show="state.mailList.selected.cc && state.mailList.selected.cc.length > 0">
<label>Cc:</label>
<span ng-repeat="u in state.mailList.selected.cc">
<span class="label" ng-class="{'label--invalid': u.secure === false, 'label--invalid-clickable': u.secure === false}" ng-mouseover="getKeyId(u.address)" wo-touch="invite(u)" wo-tooltip="#fingerprint-info">
{{u.name || u.address}}
<svg ng-show="u.secure === false"><use xlink:href="#icon-add_contact" /></svg>
</span>
</span>
</span>
</div>
</div>
<ul class="attachments" ng-show="state.mailList.selected.attachments !== undefined && state.mailList.selected.attachments.length > 0">