1
0
mirror of https://github.com/moparisthebest/mail synced 2024-11-29 20:32:15 -05:00

Refactoring login screens and lightboxes,

added general form styling
This commit is contained in:
Mario Volke 2014-11-05 16:03:48 +01:00 committed by Tankred Hase
parent e34da3bdbf
commit 915db579c4
42 changed files with 1064 additions and 1208 deletions

View File

@ -41,9 +41,8 @@
<div ng-view class="main-app-view"></div>
<!-- error dialog lightbox -->
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
<div class="lightbox dialog view-dialog" ng-include="'tpl/dialog.html'"></div>
</div><!--/.lightbox-overlay-->
<div class="lightbox lightbox--dialog" ng-class="{'lightbox--show': state.dialog.open}"
ng-include="'tpl/dialog.html'"></div>
</body>
</html>

View File

@ -54,13 +54,21 @@ var app = angular.module('mail', [
// set router paths
app.config(function($routeProvider) {
$routeProvider.when('/login', {
templateUrl: 'tpl/login.html',
controller: LoginCtrl
});
$routeProvider.when('/add-account', {
templateUrl: 'tpl/add-account.html',
controller: AddAccountCtrl
});
$routeProvider.when('/login', {
templateUrl: 'tpl/login.html',
controller: LoginCtrl
$routeProvider.when('/create-account', {
templateUrl: 'tpl/create-account.html'/*,
controller: AddAccountCtrl*/
});
$routeProvider.when('/validate-phone', {
templateUrl: 'tpl/validate-phone.html'/*,
controller: AddAccountCtrl*/
});
$routeProvider.when('/login-set-credentials', {
templateUrl: 'tpl/login-set-credentials.html',

View File

@ -19,19 +19,8 @@
@import "utilities/responsive";
@import "utilities/others";
// Components (TODO: refactor to BEM)
@import "components/lightbox";
@import "components/dialog";
// Views (TODO: refactor to BEM)
@import "views/add-account";
@import "views/account";
@import "views/privatekey-upload";
@import "views/set-passphrase";
@import "views/contacts";
@import "views/about";
@import "views/dialog";
@import "views/login";
// Blocks
// (BEM-like Naming, see http://cssguidelin.es/#bem-like-naming)
@ -46,10 +35,14 @@
@import "blocks/basics/tooltip";
@import "blocks/basics/dropdown";
@import "blocks/basics/toolbar";
@import "blocks/basics/typo";
@import "blocks/layout/app";
@import "blocks/layout/page";
@import "blocks/layout/nav";
@import "blocks/layout/action-bar";
@import "blocks/layout/mail-list-wrapper";
@import "blocks/layout/lightbox";
@import "blocks/views/mail-list";
@import "blocks/views/read";
@import "blocks/views/write";
@import "blocks/views/account";

View File

@ -5,6 +5,7 @@ $font-size-small: 14px;
$font-size-smaller: 12px;
$font-size-big: 18px;
$font-size-bigger: 22px;
$font-size-huge: 28px;
$font-family-base: "PT Sans", Arial, sans-serif;
@ -43,6 +44,8 @@ $color-touch-active: rgba(0, 0, 0, 0.1);
// Breakpoints
// -------------------------------------------
$screen-xs-max: 419px;
$screen-sm-min: 420px;
$screen-sm-max: 699px;
$screen-md-min: 700px;
$screen-md-max: 1099px;

View File

@ -41,10 +41,6 @@ textarea {
background-image: none;
}
fieldset {
border: 1px solid $color-grey-lighter;
}
// ngView
.main-app-view {
height: 100%;

View File

@ -44,6 +44,11 @@
transform: translateX(2px) translateY(2px);
}
// prevent triggering ngAnimate animations
&.ng-animate {
transition: none;
}
&[disabled],
&[aria-disabled="true"] {
cursor: not-allowed;
@ -61,6 +66,11 @@
}
}
// this modifier can be combined with other modifiers, too
&--big {
font-size: $font-size-bigger;
}
// Invalid button state
&--invalid {
background-color: $color-error;

View File

@ -1,5 +1,85 @@
// Form layout
.form {
margin: 20px auto 40px;
// same as max page with
// form should never be wider because it just doesn't look good
max-width: 400px;
&__error-message {
margin-bottom: 10px;
color: $color-error;
}
&__password-strong-message {
margin-bottom: 10px;
color: green;
}
&__row {
margin-bottom: 10px;
&--multi {
margin-bottom: 0;
@include respond-to(sm) {
display: flex;
}
}
}
&__col {
margin-bottom: 10px;
@include respond-to(sm) {
flex-grow: 1;
& + .form__col {
margin-left: 10px;
}
&--2 {
flex-grow: 2;
}
}
}
.btn {
width: 100%;
}
}
.form-fieldset {
margin: 0 0 20px;
border: 1px solid $color-border-light;
legend {
color: $color-blue;
padding: 0 0.5em;
}
& > :first-child {
margin-top: 0;
}
& > :last-child {
margin-bottom: 0;
}
&--standalone {
margin: 30px 0 40px;
}
&--error {
border-color: $color-error;
legend {
color: $color-error;
}
}
}
// Form elements
.input-text {
background-color: white;
width: 100%;
background-color: $color-bg;
border: 1px solid $color-border-light;
color: $color-text;
font-size: $font-size-base;
@ -18,8 +98,57 @@
&--error {
border-color: $color-error;
}
&--big {
font-size: $font-size-bigger;
}
}
// Attention: Webkit support only!
.input-select {
position: relative;
&:after {
position: absolute;
right: 0.5em;
top: 0;
content: '<>';
color: $color-text;
transform: rotate(90deg);
pointer-events: none;
}
select {
@extend .input-text;
padding-right: 2em;
}
}
// Attention: Webkit support only!
.input-file {
width: 100%;
background-color: $color-bg;
border: 1px solid $color-border-light;
color: $color-text;
font-size: 1em;
padding: 4px 4px;
outline: none;
&::-webkit-file-upload-button {
background-color: $color-grey-input;
border: 0;
color: $color-bg;
padding: 4px 10px;
font-family: inherit;
font-size: inherit;
line-height: inherit;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
outline: none;
cursor: pointer;
}
}
// TODO: remove, has been replace by general form class
.input-error-message {
margin: 5px 0;
padding: 0;
@ -31,7 +160,6 @@
position: relative;
width: 100%;
.input-text {
width: 100%;
padding-left: 1.8em;
}
& > svg {
@ -44,6 +172,22 @@
}
}
.input-checkbox {
display: block;
padding-left: 2em;
.checkbox {
float: left;
margin-top: 0.1em;
margin-left: -2em;
}
a {
color: $color-main;
text-decoration: underline;
}
}
.checkbox {
input[type="checkbox"] {
display: none;
@ -78,3 +222,28 @@
}
}
}
.input-email-fixed-domain {
display: flex;
& > input {
flex-grow: 1;
margin-right: 10px;
}
& > span {
font-size: $font-size-big;
flex-shrink: 0;
line-height: 38px; // magic number: depends on .input-text height
@include respond-to(md) {
font-size: $font-size-bigger;
}
}
}
/* TODO: refactore this block, simply doesn't work on mobile */
.input-code {
& > input {
display: inline-block;
width: 4em;
}
}

View File

@ -10,6 +10,10 @@
border-bottom: 0.17em solid rgba($color-black, 0.2);
border-top: 0.17em solid rgba($color-black, 0.7);
border-radius: 100%;
&--big {
font-size: 150%;
}
}
@keyframes spinner-rotation {
@ -20,3 +24,8 @@
transform: rotate(359deg);
}
}
.spinner-block {
text-align: center;
margin: 50px 0;
}

View File

@ -0,0 +1,30 @@
.typo-title {
font-size: $font-size-bigger;
color: $color-main;
margin: 0 0 10px;
@include respond-to(md) {
font-size: $font-size-huge;
}
}
.typo-paragraph {
margin: 0 0 10px;
strong {
font-weight: normal;
color: $color-main;
}
em {
font-style: italic;
}
a {
color: $color-main;
text-decoration: underline;
}
}
.typo-code {
font-family: monospace;
font-weight: bold;
}

View File

@ -0,0 +1,149 @@
.lightbox {
display: none;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 1000;
background: $color-grey-dark-alpha;
overflow: auto;
text-align: center;
@include respond-to(md) {
@include scut-vcenter-ib(".lightbox__body");
}
&__body {
position: relative;
width: 100%;
min-height: 100%;
padding: 15px;
background: $color-bg;
color: $color-text;
backface-visibility: hidden;
display: flex;
flex-direction: column;
text-align: left;
margin: 0 auto;
@include respond-to(md) {
width: 90%;
max-width: 762px;
min-height: 0;
backface-visibility: hidden;
}
}
&__header {
flex-shrink: 0;
text-align: center;
position: relative;
margin-bottom: 20px;
h2 {
margin: 0;
padding: 0;
font-size: $font-size-bigger;
font-weight: normal;
line-height: 1em;
color: $color-grey-dark;
}
}
&__close {
position: absolute;
top: 0px;
right: 0px;
display: block;
border: none;
background: none;
padding: 0 0 0 40px;
margin: 0;
color: $color-grey-dark;
outline: none;
svg {
height: 1em;
width: 1em;
fill: $color-grey-dark;
}
}
&__content {
flex-grow: 1;
overflow: hidden;
}
&__controls {
text-align: right;
margin-top: 15px;
flex-shrink: 0;
.btn {
min-width: 6em;
margin-top: 5px;
}
}
/* Modifiers */
&--dialog {
@include scut-vcenter-ib(".lightbox__body");
.lightbox__body {
min-height: 0;
max-width: 450px;
}
.lightbox__content {
padding: 0 15px;
text-align: center;
}
.lightbox__controls {
text-align: center;
margin-top: 25px;
}
}
&--show {
display: block;
}
/* ngAnimate */
&--show-add {
display: block;
opacity: 0;
@include respond-to(md) {
transition: opacity 0.3s;
}
.lightbox__body {
transform: scale(0.7);
@include respond-to(md) {
transition: transform 0.3s;
}
}
}
&--show-add-active {
opacity: 1;
.lightbox__body {
transform: scale(1);
}
}
&--show-remove {
display: block;
opacity: 1;
@include respond-to(md) {
transition: opacity 0.3s;
}
.lightbox__body {
transform: scale(1);
@include respond-to(md) {
transition: transform 0.3s;
}
}
}
&--show-remove-active {
opacity: 0;
.lightbox__body {
transform: scale(0.7);
}
}
}

View File

@ -0,0 +1,84 @@
// Simple page layout
.page {
height: 100%;
overflow-y: auto;
// disable text selection
user-select: none;
&__canvas {
min-height: 100%;
display: flex;
flex-direction: column;
padding: 10px 20px;
background: $color-grey-lighterer;
color: $color-text;
}
&__header {
margin: 45px 0;
img {
display: block;
width: 100%;
max-width: 400px;
margin: 0 auto;
}
@include respond-to(md) {
margin: 115px 0 75px;
}
}
&__main {
flex-grow: 1;
margin: 0 auto 20px;
max-width: 400px;
width: 100%;
}
&__footer {
width: 100%;
text-align: center;
font-size: $font-size-small;
color: $color-text-light;
line-height: 1.5;
nav {
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
display: inline;
white-space: nowrap;
&:after {
display: inline-block;
content: ' | ';
margin: 0 0.5em;
}
&:last-child:after {
display: none;
}
}
a {
color: inherit;
text-decoration: none;
&:hover,
&:focus {
text-decoration: underline;
}
}
}
@include respond-to(md) {
text-align: left;
nav {
float: right;
}
}
}
}

View File

@ -0,0 +1,20 @@
.account {
// TODO: remove table layout -> use <dl>
table {
margin: 50px auto 60px;
td {
padding-top: 15px;
text-align: left;
&:first-child {
text-align: right;
padding-right: 15px;
font-weight: bold;
}
a {
color: $color-main;
text-decoration: underline;
}
}
}
}

View File

@ -4,8 +4,7 @@
flex-direction: column;
@include respond-to(md) {
// this number depends on max-height set on .lightbox
height: 590px; // magic number
height: 590px; // magic number: chosen to look good
}
// Header components

View File

@ -1,16 +0,0 @@
.dialog {
padding: 0px;
color: $color-grey-dark;
a {
color: $color-blue;
}
.control {
float: right;
button {
border: 0!important;
}
}
}

View File

@ -1,140 +0,0 @@
.lightbox {
position: relative;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 2000;
@include respond-to(md) {
margin: 0 auto;
width: $lightbox-width;
max-width: $lightbox-max-width;
height: auto;
text-align: left;
backface-visibility: hidden;
}
@include respond-to(lg) {
max-width: $lightbox-max-width + 100px;
}
.lightbox-body {
position: relative;
height: 100%;
padding: $lightbox-padding;
background: #fff;
backface-visibility: hidden;
display: flex;
flex-direction: column;
@include respond-to(md) {
max-height: $lightbox-min-height;
}
@include respond-to(lg) {
max-height: $lightbox-min-height + 50px;
}
& > header {
flex-shrink: 0;
text-align: center;
position: relative;
margin-bottom: 15px;
button.close {
position: absolute;
top: 0px;
right: 0px;
display: block;
border: none;
background: none;
padding: 0 0 0 40px;
margin: 0;
color: $color-grey-dark;
outline: none;
svg {
height: 1em;
width: 1em;
fill: $color-grey-dark;
}
&.active {
top: 2px;
right: -2px;
}
}
h2 {
margin: 0;
padding: 0;
font-size: $font-size-bigger;
font-weight: normal;
line-height: 1em;
color: $color-grey-dark;
}
}
& > .content {
flex-grow: 1;
overflow: hidden;
}
}
}
.lightbox-overlay {
position: absolute;
width: 100%;
height: 100%;
display: none;
top: 0;
left: 0;
z-index: 1000;
background: $color-grey-dark-alpha;
overflow: auto;
@include respond-to(md) {
@include scut-vcenter-ib(".lightbox");
text-align: center;
}
&.show {
display: block;
}
/* ngAnimate */
&.show-add {
display: block;
opacity: 0;
@include respond-to(md) {
transition: opacity 0.3s;
}
.lightbox-body {
transform: scale(0.7);
@include respond-to(md) {
transition: transform 0.3s;
}
}
}
&.show-add-active {
opacity: 1;
.lightbox-body {
transform: scale(1);
}
}
&.show-remove {
display: block;
opacity: 1;
@include respond-to(md) {
transition: opacity 0.3s;
}
.lightbox-body {
transform: scale(1);
@include respond-to(md) {
transition: transform 0.3s;
}
}
}
&.show-remove-active {
opacity: 0;
.lightbox-body {
transform: scale(0.7);
}
}
}

View File

@ -1,7 +1,9 @@
// Actual media queries
$mediaqueries: (
sm-only: "(max-width: #{$screen-sm-max})",
xs-only: "(max-width: #{$screen-xs-max})",
sm: "(min-width: #{$screen-sm-min})",
sm-only: "(min-width: #{$screen-sm-min}) and (max-width: #{$screen-sm-max})",
md: "(min-width: #{$screen-md-min})",
md-only: "(min-width: #{$screen-md-min}) and (max-width: #{$screen-md-max})",
lg: "(min-width: #{$screen-lg-min})",

View File

@ -1,3 +1,7 @@
.u-waiting-cursor {
cursor: wait !important;
}
.u-text-center {
text-align: center;
}

View File

@ -1,15 +0,0 @@
.view-about {
@include respond-to(md) {
max-width: 550px;
}
.content {
margin: 30px auto;
text-align: center;
a {
color: $color-blue;
}
}
}

View File

@ -1,22 +0,0 @@
.view-account {
a {
color: $color-blue;
text-decoration: none;
}
table {
margin: 50px auto 60px auto;
td {
padding-top: 15px;
&:first-child {
text-align: right;
padding-right: 15px;
font-weight: bold;
}
}
}
}

View File

@ -1,193 +0,0 @@
.view-add-account {
.choose {
.choice {
padding: 20px;
p {
margin-top: 0;
}
}
hr {
margin: 30px 0;
color: $color-grey-lighter;
}
}
.create-account {
div.flex {
width: 100%;
margin: 0;
display: flex;
input[type="text"].wmail {
flex-grow: 1;
}
.domain {
font-size: $font-size-bigger;
margin: 0;
height: 38px;
line-height: 38px;
flex-shrink: 0;
@include respond-to(sm-only) {
font-size: $font-size-big;
}
}
input[type="password"] {
flex: 1;
}
input[type="password"].right {
flex: 1;
margin-right: 0;
}
}
}
.providers {
h1 {
padding: 60px 0 50px 0;
text-align: center;
margin: 0;
font-size: 32px;
line-height: 64px;
@include respond-to(sm-only) {
padding: 30px 0 20px 0;
}
}
ul {
list-style-type: none;
max-width: 320px;
width: 100%;
margin: 0 auto 30px auto;
padding: 0;
border-width: 1px;
border-style: solid;
border-color: $color-grey-lighter;
li {
position: relative;
height: 68px;
cursor: pointer;
&:hover,
&:focus {
opacity: 0.6;
}
&:active {
opacity: 1;
top: 1px;
left: 1px;
}
&:nth-child(odd) {
background-color: white;
}
&:nth-child(even) {
background-color: $color-grey-lightest;
}
&.google {
div {
width: 164px;
height: 58px;
margin: 0px auto;
padding: 8px 0;
img {
width: 164px;
height: 58px;
}
}
}
&.whiteout {
div {
width: 210px;
margin: 0 auto;
padding: 15px 0;
img {
width: 100%;
}
}
}
&.yahoo {
div {
width: 181px;
margin: 0 auto;
img {
width: 100%;
}
}
}
&.tonline {
div {
width: 271px;
margin: 0 auto;
img {
width: 100%;
}
}
}
&.outlook {
div {
width: 256px;
margin: 0 auto;
padding: 13px 0;
img {
width: 100%;
}
}
}
&.gmx {
div {
width: 115px;
margin: 0 auto;
padding: 13px 0;
img {
width: 115px;
height: 37px;
}
}
}
&.webde {
div {
width: 137px;
margin: 0 auto;
padding: 17px 0;
img {
width: 137px;
height: 31px;
}
}
}
&.other {
h3 {
margin: 0;
line-height: 68px;
font-size: 21px;
text-align: center;
}
}
}
}
}
}

View File

@ -1,23 +0,0 @@
.view-dialog {
height: auto;
@include respond-to(md) {
max-width: 350px;
}
p {
text-align: center;
max-width: 80%;
margin: 30px auto;
}
.control {
button {
min-width: 100px;
&.ng-animate {
transition: none;
}
}
}
}

View File

@ -1,208 +0,0 @@
.view-login {
position: relative;
height: 100%;
background-color: $color-grey-lightest;
color: $color-grey-dark;
text-align: center;
padding: 20px;
overflow-y: auto;
.logo {
max-width: 700px;
margin: 45px auto;
img {
display: block;
max-width: 50%;
width: 320px;
}
@include respond-to(md) {
margin: 115px auto 75px;
}
}
.working {
text-align: center;
}
.spinner {
font-size: 150%;
}
.content {
max-width: 400px;
margin-left: auto;
margin-right: auto;
text-align: left;
b, a {
color: $color-blue;
}
button, a.btn {
margin-right: 10px;
margin-bottom: 10px;
width: 100%;
}
p, label {
line-height: 150%;
}
div {
margin: 20px 0;
}
fieldset {
margin: 30px 0 40px;
legend {
color: $color-blue;
}
p {
margin: 0;
}
}
input {
margin-right: 10px;
}
label,
input[type="tel"],
input[type="text"],
input[type="email"],
input[type="number"],
input[type="password"] {
margin-bottom: 10px;
width: 100%;
}
input.token {
width: auto;
}
input[type=file] {
width: 100%;
background-color: white;
border-width: 1px;
border-style: solid;
border-color: $color-grey-lighter;
color: $color-grey-input;
font-size: 1em;
padding: 4px 4px;
outline: none;
&::-webkit-file-upload-button {
background-color: $color-grey-input;
border-width: 0px;
border-style: solid;
color: white;
padding: 4px 10px;
font-family: inherit;
font-size: inherit;
line-height: inherit;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
outline: none;
cursor: pointer;
}
}
}
}
.view-login-existing {
}
.view-login-initial {
.content {
form {
.option {
width: 90%;
font-size: $font-size-small;
margin: 0 auto;
}
.terms {
margin-top: 30px;
margin-bottom: 15px;
}
.newsletter {
margin-bottom: 40px;
}
}
}
}
.view-login-privatekey-download {
.content {
fieldset {
margin-top: 20px;
}
.code {
max-width: 240px;
margin: 0 auto;
input {
margin-right: 0;
width: auto;
}
}
}
}
.view-login-set-credentials {
.content {
b, a {
text-decoration: none;
}
.connection-error {
margin: 30px 0;
p {
margin-bottom: 15px;
}
}
.details {
fieldset {
margin: 0 0 10px 0;
select {
width: 100%;
}
div {
width: 100%;
margin: 0;
display: flex;
input[type="text"] {
flex: 2;
}
input[type="number"] {
flex: 1;
margin-right: 0;
}
}
label {
position:relative
}
label:after {
content: '<>';
color: $color-grey-dark;
transform:rotate(90deg);
right: 8px;
top: -3px;
position:absolute;
pointer-events:none;
}
}
}
}
}

View File

@ -1,25 +0,0 @@
.view-privatekey-upload {
a {
color: $color-blue;
}
.step {
margin: 20px 0;
h2 {
font-family: "Lucida Sans Typewriter", "Lucida Console", Monaco, "Bitstream Vera Sans Mono", monospace;
}
.working {
text-align: center;
font-size: 30px;
margin: 70px;
}
}
button.ng-animate {
transition: none;
}
}

View File

@ -1,38 +0,0 @@
.view-set-passphrase {
p {
margin: 40px auto 0;
width: 90%;
}
.passphrase-label-ok {
color: green;
}
.inputs {
margin: 40px 60px 30px;
div {
margin: 5px 0;
}
}
table {
margin: 40px auto 60px auto;
td {
padding-top: 16px;
&:first-child {
text-align: right;
padding-right: 16px;
font-weight: bold;
}
}
td.no-padding {
padding-top: 0;
}
}
}

View File

@ -1,17 +1,23 @@
<div class="lightbox-body" ng-controller="AboutCtrl">
<header>
<button class="close" wo-touch="state.about.toggle(false)" data-action="lightbox-close">
<div class="lightbox__body" ng-controller="AboutCtrl">
<header class="lightbox__header">
<button class="lightbox__close" wo-touch="state.about.toggle(false)" data-action="lightbox-close">
<svg><use xlink:href="#icon-close" /><title>Close</title></svg>
</button>
</header>
<div class="content">
<div class="lightbox__content">
<p class="typo-paragraph">
<img src="img/icon-128.png">
<h2>Whiteout Mail</h2>
<p>Version {{version}}</p>
<p>&copy; {{ date | date:'yyyy'}} Whiteout Networks GmbH</p>
<p><a href="https://whiteout.io/imprint.html" target="_blank">Imprint</a> &middot; <a href="https://whiteout.io/privacy-service.html" target="_blank">Privacy</a> &middot; <a href="https://whiteout.io/terms.html" target="_blank">Terms</a> &middot; <a href="https://github.com/whiteout-io/mail-html5#license" target="_blank">Licenses</a></p>
</p>
</div><!-- /.content -->
</div><!-- /.lightbox-body -->
<h2 class="typo-title">Whiteout Mail</h2>
<p class="typo-paragraph">Version {{version}}</p>
<p class="typo-paragraph">&copy; {{ date | date:'yyyy'}} Whiteout Networks GmbH</p>
<p class="typo-paragraph">
<a href="https://whiteout.io/imprint.html" target="_blank">Imprint</a> &middot;
<a href="https://whiteout.io/privacy-service.html" target="_blank">Privacy</a> &middot;
<a href="https://whiteout.io/terms.html" target="_blank">Terms</a> &middot;
<a href="https://github.com/whiteout-io/mail-html5#license" target="_blank">Licenses</a>
</p>
</div>
</div>

View File

@ -1,14 +1,13 @@
<div class="lightbox-body" ng-controller="AccountCtrl">
<header>
<div class="lightbox__body" ng-controller="AccountCtrl">
<header class="lightbox__header">
<h2>Account</h2>
<button class="close" wo-touch="state.account.toggle(false)" data-action="lightbox-close">
<button class="lightbox__close" wo-touch="state.account.toggle(false)" data-action="lightbox-close">
<svg><use xlink:href="#icon-close" /><title>Close</title></svg>
</button>
</header>
<div class="content">
<div class="dialog view-account">
<div class="lightbox__content">
<div class="account">
<table>
<tbody>
<tr>
@ -29,12 +28,11 @@
</tr>
</tbody>
</table>
<div class="control">
<button wo-touch="state.account.toggle(false); state.setPassphrase.toggle(true)" class="btn btn--secondary">Set passphrase</button>
<button wo-touch="exportKeyFile()" class="btn">Export keypair</button>
</div>
</div>
</div><!-- /.view-account -->
</div><!-- /.content -->
</div><!-- /.lightbox-body -->
<footer class="lightbox__controls">
<button wo-touch="state.account.toggle(false); state.setPassphrase.toggle(true)" class="btn btn--secondary">Set passphrase</button>
<button wo-touch="exportKeyFile()" class="btn">Export keypair</button>
</footer>
</div>

View File

@ -1,189 +1,28 @@
<div class="view-login view-add-account">
<div ng-show="step === 1">
<div class="logo">
<section class="page">
<div class="page__canvas">
<header class="page__header">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
<div class="content choose">
<div class="choice">
<p><b>Create Whiteout account.</b> Create a new fully encrypted Whiteout Mailbox.</p>
<button class="btn" wo-touch="goTo(2)">Create new account</button>
</header>
<main class="page__main">
<h2 class="typo-title">Connect your email account</h2>
<p class="typo-paragraph">Enter your email to connect with whiteout.</p>
<form class="form" name="form">
<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
<p class="form__error-message" ng-show="form.$invalid">Please fill out all required fields!</p>
<div class="form__row">
<input class="input-text input-text--big" required type="mail" placeholder="Enter email address">
</div>
<hr>
<div class="choice">
<p><b>Login to IMAP account.</b> Connect Whiteout Mail to any existing email account via IMAP.</p>
<button class="btn btn--secondary" wo-touch="goTo(4)">Login to existing</button>
<div class="spinner-block" ng-show="busy">
<span class="spinner spinner--big"></span>
</div>
</div>
</div>
<div ng-show="step === 2">
<div class="logo">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
<div class="content create-account">
<p><b>Create Whiteout account.</b> Please fill out the following form. You will need a <i>beta access code</i> during the private beta period.</p>
<form name="form">
<label class="input-error-message" ng-show="errMsg">{{errMsg}}</label>
<label class="input-error-message" ng-show="form.$invalid">Please fill out all required fields!</label>
<div class="flex">
<input class="input-text wmail" ng-model="user" required type="text" pattern='^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))' placeholder="User name" focus-me="step === 2">
<span class="domain">@wmail.io</span>
</div>
<input class="input-text" type="text" ng-model="realname" placeholder="Full name (optional)"></input>
<div class="flex">
<input class="input-text" ng-model="pass" required type="password" placeholder="Password" pattern=".{3,30}">
<input class="input-text right" ng-model="confirmPass" required type="password" placeholder="Confirm password" ng-class="{'input-text--error': (pass || confirmPass) && pass !== confirmPass}">
</div>
<input class="input-text" type="tel" ng-model="phone" required placeholder="Mobile phone number (e.g. +49 170 1234567)"/>
<input class="input-text" type="text" class="input-text" ng-model="betaCode" required placeholder="Beta access code">
<div class="working" ng-show="busy">
<span class="spinner"></span>
</div>
<div>
<button class="btn" type="submit" ng-click="createWhiteoutAccount()">Create</button>
<div class="form__row">
<button class="btn btn--big" type="submit">Connect</button>
</div>
</form>
<p class="typo-paragraph">
Or create a new fully encrypted <a href="#">whiteout mailbox</a>.
</p>
</main>
<div ng-include="'tpl/page-footer.html'"></div>
</div>
</div>
<div ng-show="step === 3">
<div class="logo">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
<div class="content">
<p><b>Validate phone number.</b> We have sent you a validation code via SMS. Please enter this code to confirm your phone number.</p>
<form name="formValidate">
<label class="input-error-message" ng-show="errMsgValidate">{{errMsgValidate}}</label>
<br>
<input type="text" class="input-text token" size="6" maxlength="6" ng-model="token" placeholder="Code" focus-me="step === 3" required pattern="([a-zA-Z0-9]*)">
<div class="working" ng-show="busyValidate">
<span class="spinner"></span>
</div>
<div>
<button class="btn" type="submit" ng-click="validateUser()">Confirm code</button>
</div>
</form>
</div>
</div>
<div class="providers" ng-show="step === 4">
<h1>Select account</h1>
<ul>
<li class="whiteout" wo-tooltip="#whiteout-info" wo-touch="connectTo('wmail')">
<div><img src="img/whiteout_logo.svg" alt="Whiteout Mailbox"></div>
</li>
<li class="google" wo-tooltip="#google-info" wo-touch="connectToGoogle()">
<div><img src="img/google_logo.png" alt="Google Mail"></div>
</li>
<li class="outlook" wo-tooltip="#outlook-info" wo-touch="connectTo('outlook')">
<div><img src="img/outlook_logo.jpg" alt="Outlook.com"></div>
</li>
<li class="yahoo" wo-tooltip="#yahoo-info" wo-touch="connectTo('yahoo')">
<div><img src="img/yahoo_logo.png" alt="Yahoo! Mail"></div>
</li>
<li class="gmx" wo-tooltip="#gmx-info" wo-touch="connectTo('gmx')">
<div><img src="img/gmx_logo.jpg" alt="GMX.net"></div>
</li>
<li class="webde" wo-tooltip="#webde-info" wo-touch="connectTo('webde')">
<div><img src="img/webde_logo.jpg" alt="Web.de"></div>
</li>
<li class="tonline" wo-tooltip="#tonline-info" wo-touch="connectTo('tonline')">
<div><img src="img/tonline_logo.jpg" alt="T-Online"></div>
</li>
<li class="other" wo-tooltip="#custom-info" wo-touch="connectTo('custom')">
<h3>Custom server...</h3>
</li>
</ul>
</div>
</div>
<!-- tooltips -->
<div id="google-info" class="tooltip u-hidden-sm">
<div class="tooltip__arrow"></div>
<div class="tooltip__title">Google Account</div>
<div class="tooltip__content">
<p>Connect Whiteout Mail to your Gmail or Google Apps account.</p>
<p>Encrypted and cleartext messages are stored on Google's servers.</p>
<p>Your emails and password remain on your device and are never sent to our servers.</p>
</div>
</div><!--/.tooltip-->
<div id="whiteout-info" class="tooltip u-hidden-sm">
<div class="tooltip__arrow"></div>
<div class="tooltip__title">Whiteout Mailbox</div>
<div class="tooltip__content">
<p>Connect Whiteout Mail to your fully encrypted Whiteout Mailbox (hosted in Europe).</p>
<p>Incoming cleartext messages are encrypted with your public PGP key before being stored in your inbox.</p>
<p>This way your email is protected against hackers and can only be read on your device.</p>
</div>
</div><!--/.tooltip-->
<div id="yahoo-info" class="tooltip u-hidden-sm">
<div class="tooltip__arrow"></div>
<div class="tooltip__title">Yahoo Mail</div>
<div class="tooltip__content">
<p>Connect Whiteout Mail to your Yahoo Mail account.</p>
<p>Encrypted and cleartext messages are stored on Yahoo's servers.</p>
<p>Your emails and password remain on your device and are never sent to our servers.</p>
</div>
</div><!--/.tooltip-->
<div id="tonline-info" class="tooltip u-hidden-sm">
<div class="tooltip__arrow"></div>
<div class="tooltip__title">T-Online Account</div>
<div class="tooltip__content">
<p>Connect Whiteout Mail to your T-Online account.</p>
<p>Encrypted and cleartext messages are stored on T-Online's servers.</p>
<p>Your emails and password remain on your device and are never sent to our servers.</p>
</div>
</div><!--/.tooltip-->
<div id="outlook-info" class="tooltip u-hidden-sm">
<div class="tooltip__arrow"></div>
<div class="tooltip__title">Outlook.com Account</div>
<div class="tooltip__content">
<p>Connect Whiteout Mail to your Outlook.com account.</p>
<p>Encrypted and cleartext messages are stored on Microsoft's servers.</p>
<p>Your emails and password remain on your device and are never sent to our servers.</p>
</div>
</div><!--/.tooltip-->
<div id="gmx-info" class="tooltip u-hidden-sm">
<div class="tooltip__arrow"></div>
<div class="tooltip__title">GMX.net Account</div>
<div class="tooltip__content">
<p>Connect Whiteout Mail to your GMX.net account.</p>
<p>Encrypted and cleartext messages are stored on GMX's servers.</p>
<p>Your emails and password remain on your device and are never sent to our servers.</p>
</div>
</div><!--/.tooltip-->
<div id="webde-info" class="tooltip u-hidden-sm">
<div class="tooltip__arrow"></div>
<div class="tooltip__title">Web.de Account</div>
<div class="tooltip__content">
<p>Connect Whiteout Mail to your Web.de account.</p>
<p>Encrypted and cleartext messages are stored on Web.de's servers.</p>
<p>Your emails and password remain on your device and are never sent to our servers.</p>
</div>
</div><!--/.tooltip-->
<div id="custom-info" class="tooltip u-hidden-sm">
<div class="tooltip__arrow"></div>
<div class="tooltip__title">Custom server</div>
<div class="tooltip__content">
<p>Connect Whiteout Mail to your own email server.</p>
<p>Encrypted and cleartext messages are stored on your server.</p>
<p>Your emails and password remain on your device and are never sent to our servers.</p>
</div>
</div><!--/.tooltip-->
</section>

View File

@ -1,12 +1,12 @@
<div class="lightbox-body" ng-controller="ContactsCtrl">
<header>
<div class="lightbox__body" ng-controller="ContactsCtrl">
<header class="lightbox__header">
<h2>Contacts</h2>
<button class="close" wo-touch="state.contacts.toggle(false)" data-action="lightbox-close">
<button class="lightbox__close" wo-touch="state.contacts.toggle(false)" data-action="lightbox-close">
<svg><use xlink:href="#icon-close" /><title>Close</title></svg>
</button>
</header>
<div class="content">
<div class="lightbox__content">
<div class="view-contacts">
<div class="key-controls">
@ -46,8 +46,6 @@
</div><!--/.key-list-->
</div><!-- /.view-contacts -->
</div><!-- /.content -->
</div>
</div><!-- /.lightbox-body -->
</div>

View File

@ -0,0 +1,46 @@
<section class="page">
<div class="page__canvas">
<header class="page__header">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</header>
<main class="page__main">
<h2 class="typo-title">Create Whiteout account</h2>
<p class="typo-paragraph">Please fill out the following form. You will need a <em>beta access code</em> during the private beta period.</p>
<form class="form" name="form">
<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
<p class="form__error-message" ng-show="form.$invalid">Please fill out all required fields!</p>
<div class="form__row">
<div class="input-email-fixed-domain">
<input class="input-text" ng-model="user" required type="text"
pattern='^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))' placeholder="User name" focus-me="step === 2">
<span>@wmail.io</span>
</div>
</div>
<div class="form__row">
<input class="input-text" type="text" ng-model="realname" placeholder="Full name (optional)">
</div>
<div class="form__row form__row--multi">
<div class="form__col">
<input class="input-text" ng-model="pass" required type="password" placeholder="Password" pattern=".{3,30}">
</div>
<div class="form__col">
<input class="input-text right" ng-model="confirmPass" required type="password" placeholder="Confirm password" ng-class="{'input-text--error': (pass || confirmPass) && pass !== confirmPass}">
</div>
</div>
<div class="form__row">
<input class="input-text" type="tel" ng-model="phone" required placeholder="Mobile phone number (e.g. +49 170 1234567)">
</div>
<div class="form__row">
<input class="input-text" type="text" ng-model="betaCode" required placeholder="Beta access code">
</div>
<div class="spinner-block" ng-show="busy">
<span class="spinner spinner--big"></span>
</div>
<div class="form__row">
<button class="btn" type="submit" ng-click="createWhiteoutAccount()">Create</button>
</div>
</form>
</main>
<div ng-include="'tpl/page-footer.html'"></div>
</div>
</section>

View File

@ -12,26 +12,20 @@
</div>
<!-- lightbox -->
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'write'}">
<div class="lightbox" ng-include="'tpl/write.html'"></div>
</div>
<div class="lightbox" ng-class="{'lightbox--show': state.lightbox === 'write'}"
ng-include="'tpl/write.html'"></div>
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'account'}">
<div class="lightbox" ng-include="'tpl/account.html'"></div>
</div>
<div class="lightbox lightbox--dialog" ng-class="{'lightbox--show': state.lightbox === 'account'}"
ng-include="'tpl/account.html'"></div>
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'set-passphrase'}">
<div class="lightbox" ng-include="'tpl/set-passphrase.html'"></div>
</div>
<div class="lightbox" ng-class="{'lightbox--show': state.lightbox === 'set-passphrase'}"
ng-include="'tpl/set-passphrase.html'"></div>
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'privatekey-upload'}">
<div class="lightbox" ng-include="'tpl/privatekey-upload.html'"></div>
</div>
<div class="lightbox" ng-class="{'lightbox--show': state.lightbox === 'privatekey-upload'}"
ng-include="'tpl/privatekey-upload.html'"></div>
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'contacts'}">
<div class="lightbox" ng-include="'tpl/contacts.html'"></div>
</div>
<div class="lightbox" ng-class="{'lightbox--show': state.lightbox === 'contacts'}"
ng-include="'tpl/contacts.html'"></div>
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'about'}">
<div class="lightbox view-about" ng-include="'tpl/about.html'"></div>
</div>
<div class="lightbox lightbox--dialog" ng-class="{'lightbox--show': state.lightbox === 'about'}"
ng-include="'tpl/about.html'"></div>

View File

@ -1,18 +1,19 @@
<div class="lightbox-body" ng-controller="DialogCtrl">
<header>
<div class="lightbox__body" ng-controller="DialogCtrl">
<header class="lightbox__header">
<h2>{{state.dialog.title}}</h2>
<button class="close" wo-touch="confirm(false)" data-action="lightbox-close">
<button class="lightbox__close" wo-touch="confirm(false)" data-action="lightbox-close">
<svg><use xlink:href="#icon-close" /><title>Close</title></svg>
</button>
</header>
<div class="content">
<p>{{state.dialog.message}} <a ng-show="state.dialog.faqLink" href="{{state.dialog.faqLink}}" target="_blank">Learn more</a></p>
<div class="control">
<button wo-touch="confirm(false)" class="btn btn-secondary" ng-show="state.dialog.showNegativeBtn">{{state.dialog.negativeBtnStr}}</button>
<div class="lightbox__content">
<p class="typo-paragraph">{{state.dialog.message}} <a ng-show="state.dialog.faqLink" href="{{state.dialog.faqLink}}" target="_blank">Learn more</a></p>
</div>
<footer class="lightbox__controls">
<button wo-touch="confirm(false)" class="btn btn--secondary" ng-show="state.dialog.showNegativeBtn">{{state.dialog.negativeBtnStr}}</button>
<!-- only show bug report button if we can actually report a bug, i.e. the writer is attached to the scope -->
<button wo-touch="confirm(true)" class="btn" ng-show="!state.writer || !state.dialog.showBugReporter">{{state.dialog.positiveBtnStr}}</button>
<button wo-touch="confirm(true); state.writer.reportBug()" class="btn" ng-show="state.writer && state.dialog.showBugReporter">Report bug</button>
</div>
</div><!-- /.content -->
</div><!-- /.lightbox-body -->
</footer>
</div>

View File

@ -1,19 +1,31 @@
<div class="view-login view-login-existing">
<div class="logo">
<section class="page">
<div class="page__canvas">
<header class="page__header">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
</header>
<main class="page__main">
<h2 class="typo-title">Unlock mailbox</h2>
<p class="typo-paragraph">Please enter your passphrase to unlock the mailbox.</p>
<form class="form">
<!-- TODO add error messages -->
<!--<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
<p class="form__error-message" ng-show="form.$invalid">Please fill out all required fields!</p>-->
<div class="content">
<p><b>Unlock mailbox.</b> Please enter your passphrase to unlock the mailbox.</p>
<form>
<div>
<input class="input-text" type="password" ng-model="passphrase" ng-change="change()" ng-class="{'input-text--error':incorrect}" placeholder="Passphrase" tabindex="1" focus-me="true">
<div class="form__row">
<input class="input-text input-text--big" type="password" ng-model="passphrase" ng-change="change()"
ng-class="{'input-text--error':incorrect}" placeholder="Passphrase" tabindex="1" focus-me="true">
</div>
<a href="https://whiteout.io/revocation.html" title="Click here to reset your account." target="_blank">Forgot your passphrase?</a>
<div>
<button type="submit" wo-touch="confirmPassphrase()" class="btn" data-icon="&#xe009;" ng-disabled="!buttonEnabled" tabindex="2">Unlock</button>
<div class="form__row">
<button class="btn btn--big" type="submit" wo-touch="confirmPassphrase()" ng-disabled="!buttonEnabled" tabindex="2">
<svg role="presentation"><use xlink:href="#icon-decrypted" /></svg>
Unlock
</button>
</div>
</form>
</div><!--/content-->
</div>
<p class="typo-paragraph">
<a href="https://whiteout.io/revocation.html" title="Click here to reset your account." target="_blank">Forgot your passphrase?</a>
</p>
</main>
<div ng-include="'tpl/page-footer.html'"></div>
</div>
</section>

View File

@ -1,37 +1,57 @@
<div class="view-login view-login-initial" ng-class="{'u-waiting-cursor': state.ui === 3}">
<div class="logo">
<section class="page" ng-class="{'u-waiting-cursor': state.ui === 3}">
<div class="page__canvas">
<header class="page__header">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
<div class="content">
</header>
<main class="page__main">
<div ng-show="state.ui === 1">
<p><b>PGP key.</b> You can either import an existing PGP key or generate a new one. Your private key remains on your device and is not sent to our servers.</p>
<h2 class="typo-title">PGP key</h2>
<p class="typo-paragraph">
You can either import an existing PGP key or generate a new one.
Your private key remains on your device and is not sent to our servers.
</p>
<form>
<div class="option terms">
<input type="checkbox" ng-model="state.agree" id="cb-agree">
<label for="cb-agree">I agree to the Whiteout Networks <a href="https://whiteout.io/terms.html" target="_blank">Terms of Service</a> and have read the <a href="https://whiteout.io/privacy-service.html" target="_blank">Privacy Policy</a>.</label>
<form class="form" name="form">
<!-- TODO: remove error dialog and use inline error messages -->
<!--<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
<p class="form__error-message" ng-show="form.$invalid">Please fill out all required fields!</p>-->
<div class="form__row">
<label class="input-checkbox">
<span class="checkbox">
<input type="checkbox" ng-model="state.agree">
<span class="input-checkbox__box"><svg role="presentation"><use xlink:href="#icon-check" /></svg></span>
</span>
I agree to the Whiteout Networks <a href="https://whiteout.io/terms.html" target="_blank">Terms of Service</a> and have read the <a href="https://whiteout.io/privacy-service.html" target="_blank">Privacy Policy</a>
</label>
</div>
<div class="option newsletter">
<input type="checkbox" ng-model="state.newsletter" id="cb-newsletter">
<label for="cb-newsletter">Stay up to date on Whiteout Networks products and important announcements.</label>
<div class="form__row">
<label class="input-checkbox">
<span class="checkbox">
<input type="checkbox" ng-model="state.newsletter">
<span class="input-checkbox__box"><svg role="presentation"><use xlink:href="#icon-check" /></svg></span>
</span>
Stay up to date on Whiteout Networks products and important announcements.
</label>
</div>
<div>
<button type="submit" wo-touch="generateKey()" class="btn"tabindex="3">Generate new key</button>
<button wo-touch="importKey()" class="btn btn--secondary">Import existing key</button>
<div class="form__row">
<button type="submit" wo-touch="generateKey()" class="btn" tabindex="3">Generate new key</button>
</div>
<div class="form__row">
<button type="button" wo-touch="importKey()" class="btn btn--secondary">Import existing key</button>
</div>
</form>
</div>
<div ng-show="state.ui === 2">
<p><b>Generating key.</b> Please stand by. This can take a while...</p>
<div class="working">
<span class="spinner"></span>
</div><!--/.working-->
<h2 class="typo-title">Generating key</h2>
<p class="typo-paragraph">
Please stand by. This can take a while…
</p>
<div class="u-text-center">
<span class="spinner spinner--big"></span>
</div>
</div><!--/content-->
</div>
</div>
</main>
<div ng-include="'tpl/page-footer.html'"></div>
</div>
</section>

View File

@ -1,25 +1,47 @@
<div class="view-login">
<div class="logo">
<section class="page">
<div class="page__canvas">
<header class="page__header">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
</header>
<main class="page__main">
<h2 class="typo-title">Import PGP key</h2>
<p class="typo-paragraph">Please import an existing key from the file system.</p>
<div class="content">
<p><b>Import PGP key.</b> Please import an existing key from the file system.</p>
<fieldset>
<form class="form" name="form">
<fieldset class="form-fieldset form-fieldset--standalone">
<legend>On a mobile device?</legend>
<p>If you cannot import your key via a USB stick, you can setup <i>Key sync</i> on a desktop PC to securely transfer your PGP key over the Whiteout cloud. <a href="https://blog.whiteout.io/2014/07/07/secure-pgp-key-sync-a-proposal/" target="_blank">Learn more</a>.</p>
<p class="typo-paragraph">
If you cannot import your key via a USB stick, you can setup <em>Key sync</em>
on a desktop PC to securely transfer your PGP key over the Whiteout cloud.
<a href="https://blog.whiteout.io/2014/07/07/secure-pgp-key-sync-a-proposal/" target="_blank">Learn more</a>.
</p>
</fieldset>
<form>
<div>
<input type="file" accept=".asc" file-reader tabindex="1">
<!-- TODO -->
<!--<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
<p class="form__error-message" ng-show="form.$invalid">Please fill out all required fields!</p>-->
<div class="form__row">
<input class="input-file" type="file" accept=".asc" file-reader tabindex="1">
</div>
<div>
<input class="input-text" type="password" ng-model="passphrase" ng-class="{'input-text--error':incorrect}" placeholder="Passphrase" tabindex="2">
<div class="form__row">
<input class="input-text" type="password" ng-model="passphrase"
ng-class="{'input-text--error':incorrect}" placeholder="Passphrase" tabindex="2">
</div>
<!-- TODO -->
<!--<div class="spinner-block" ng-show="busy">
<span class="spinner spinner--big"></span>
</div>-->
<div class="form__row">
<button type="submit" wo-touch="confirmPassphrase()" class="btn" ng-disabled="!key" tabindex="3">Import</button>
</div>
<a href="https://whiteout.io/revocation.html" title="Click here to reset your account." target="_blank">Lost your keyfile or passphrase?</a>
<div><button type="submit" wo-touch="confirmPassphrase()" class="btn" ng-disabled="!key" tabindex="3">Import</button>
</form>
<p class="typo-paragraph">
<a href="https://whiteout.io/revocation.html" title="Click here to reset your account." target="_blank">
Lost your keyfile or passphrase?
</a>
</p>
</main>
<div ng-include="'tpl/page-footer.html'"></div>
</div>
</div>
</section>

View File

@ -1,30 +1,49 @@
<div class="view-login view-login-privatekey-download">
<div class="logo">
<section class="page">
<div class="page__canvas">
<header class="page__header">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
</header>
<main class="page__main">
<div class="content">
<div ng-show="step === 1">
<h2 class="typo-title">Key sync</h2>
<p class="typo-paragraph">We have sent you an email containing a recovery token. Please copy and paste the token below to download your key.</p>
<form class="form">
<!-- TODO add error messages -->
<!--<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
<p class="form__error-message" ng-show="form.$invalid">Please fill out all required fields!</p>-->
<div class="step" ng-show="step === 1">
<p><b>Key sync.</b> We have sent you an email containing a recovery token. Please copy and paste the token below to download your key.</p>
<div class="form__row">
<input type="text" class="input-text input-text--big" size="6" maxlength="6" ng-model="recoveryToken" placeholder="Token" focus-me="step === 1" pattern="([a-zA-Z0-9]*)">
</div>
<div class="form__row">
<button class="btn btn--big" wo-touch="goForward()">Confirm token</button>
</div>
</form>
<input type="text" class="input-text token" size="6" maxlength="6" ng-model="recoveryToken" placeholder="Token" focus-me="step === 1" pattern="([a-zA-Z0-9]*)">
<fieldset>
<form class="form">
<fieldset class="form-fieldset">
<legend>Got USB?</legend>
<p>You can also import the key file manually if you're on a device with USB access and your key is on a flash drive.</p>
<p class="typo-paragraph">
You can also import the key file manually if you're on a device with USB access and your key is on a flash drive.
</p>
</fieldset>
<div>
<button class="btn" wo-touch="goForward()">Confirm token</button>
<div class="form__row">
<a class="btn btn--secondary" href="#login-new-device">Import key file</a>
</div>
</form>
</div>
<div class="step" ng-show="step === 2">
<p><b>Key sync.</b> Please enter the keychain code you wrote down during sync setup.</p>
<div ng-show="step === 2">
<h2 class="typo-title">Key sync</h2>
<p class="typo-paragraph">Please enter the keychain code you wrote down during sync setup.</p>
<form class="form">
<!-- TODO add error messages -->
<!--<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
<p class="form__error-message" ng-show="form.$invalid">Please fill out all required fields!</p>-->
<div class="code">
<div class="form__row">
<div class="input-code">
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code0" focus-me="step === 2" focus-next ng-paste="handlePaste($event)"> -
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code1" focus-next> -
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code2" focus-next> -
@ -32,12 +51,17 @@
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code4" focus-next> -
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code5">
</div>
<!--<a href="https://whiteout.io/revocation.html" title="Click here to reset your account." target="_blank">Lost your keychain code?</a>-->
<div>
</div>
<div class="form__row">
<button class="btn" wo-touch="goForward()">Complete sync</button>
</div>
</form>
<p class="typo-paragraph">
<a href="https://whiteout.io/revocation.html" title="Click here to reset your account." target="_blank">Lost your keychain code?</a>
</p>
</div>
</div><!--/content-->
</div>
</main>
<div ng-include="'tpl/page-footer.html'"></div>
</div>
</section>

View File

@ -1,76 +1,126 @@
<div class="view-login view-login-set-credentials">
<div class="logo">
<section class="page">
<div class="page__canvas">
<header class="page__header">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
</header>
<main class="page__main">
<h2 class="typo-title">Login</h2>
<p class="typo-paragraph" ng-hide="useOAuth">
Please enter your email address and password.
The password is used to authenticate directly
with your mail provider and is not sent to our servers.
</p>
<p class="typo-paragraph" ng-show="useOAuth">
Please confirm your email address. Your account will
authenticate directly with your mail provider. Your
credentials are never sent to our servers.
</p>
<div class="content">
<p ng-hide="useOAuth"><b>Login.</b> Please enter your email address and password. The password is used to authenticate directly with your mail provider and is not sent to our servers.</p>
<p ng-show="useOAuth"><b>Login.</b> Please confirm your email address. Your account will authenticate directly with your mail provider. Your credentials are never sent to our servers.</p>
<form name="form">
<div>
<fieldset class="connection-error" ng-show="connectionError">
<form class="form" name="form">
<fieldset class="form-fieldset form-fieldset--standalone form-fieldset--error" ng-show="connectionError">
<legend>Connection Error</legend>
<p class="input-error-message">{{connectionError.message}}</p>
<p ng-show="connectionError.underlyingError" class="input-error-message">Underlying Cause: {{connectionError.underlyingError.message}}</p>
<a class="input-error-message" href="https://github.com/whiteout-io/mail-html5/wiki/FAQ#troubleshooting" target="_blank">Find out more in the FAQ.</a>
<p class="typo-paragraph">{{connectionError.message}}</p>
<p class="typo-paragraph" ng-show="connectionError.underlyingError">
Underlying Cause: <em>{{connectionError.underlyingError.message}}</em>
</p>
<p class="typo-paragraph">
<a href="https://github.com/whiteout-io/mail-html5/wiki/FAQ#troubleshooting" target="_blank">
Find out more in the FAQ.
</a>
</p>
</fieldset>
<label class="input-error-message" ng-show="form.$invalid || credentialsIncomplete">Please fill out all required fields!</label>
<p class="form__error-message" ng-show="form.$invalid || credentialsIncomplete">
Please fill out all required fields!
</p>
<div class="form__row">
<input class="input-text" type="email" required ng-model="emailAddress"
placeholder="Email address" focus-me="true" tabindex="1" spellcheck="false">
</div>
<div class="form__row">
<input class="input-text" type="text" ng-model="realname"
placeholder="Full name (optional)" tabindex="2">
</div>
<div class="form__row" ng-hide="useOAuth">
<input ng-required="!useOAuth" class="input-text"
ng-class="{'input-text--error': connectionError}" type="password"
ng-model="password" placeholder="Password" tabindex="3">
</div>
<p class="typo-paragraph">
<br>
<input class="input-text" type="email" required ng-model="emailAddress" placeholder="Email address" focus-me="true" tabindex="1" spellcheck="false"></input>
<input class="input-text" type="text" ng-model="realname" placeholder="Full name (optional)" tabindex="2"></input>
<input ng-hide="useOAuth" ng-required="!useOAuth" class="input-text" ng-class="{'input-text--error': connectionError}" type="password" ng-model="password" placeholder="Password" tabindex="3">
</div><!--/credentials-->
<a href="javascript:;" wo-touch='showDetails = !showDetails; $event.preventDefault()'>
{{showDetails ? "Hide Options" : "Show Options"}}
</a>
<br><br>
</p>
<a href="#" wo-touch='showDetails = !showDetails; $event.preventDefault()'>{{showDetails ? "Hide Options" : "Show Options"}}</a>
<div ng-show="showDetails">
<div class="form__row" ng-hide="useOAuth">
<input class="input-text" type="text" ng-model="username" placeholder="User (optional)">
</div>
<div class='details' ng-show='showDetails'>
<input ng-hide="useOAuth" class="input-text username" type="text" ng-model="username" placeholder="User (optional)"></input>
<fieldset>
<fieldset class="form-fieldset">
<legend>IMAP</legend>
<div>
<input required ng-disabled="hasProviderPreset" class="input-text" type="text" ng-model="imapHost" placeholder="Host" pattern="^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></input>
<input required ng-disabled="hasProviderPreset" class="input-text" type="number" ng-model="imapPort" placeholder="Port" min="0" max="65535" step="1" pattern="\d+"></input>
<div class="form__row form__row--multi">
<div class="form__col form__col--2">
<input required ng-disabled="hasProviderPreset" class="input-text" type="text"
ng-model="imapHost" placeholder="Host"
pattern="^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
</div>
<label>
<select class="input-text" required ng-disabled="hasProviderPreset" ng-model="imapEncryption">
<div class="form__col">
<input required ng-disabled="hasProviderPreset" class="input-text" type="number"
ng-model="imapPort" placeholder="Port" min="0" max="65535" step="1" pattern="\d+">
</div>
</div>
<div class="form__row">
<label class="input-select">
<select required ng-disabled="hasProviderPreset" ng-model="imapEncryption">
<option value="" disabled selected style="display:none">Encryption method</option>
<option value="2">TLS</option>
<option value="1">STARTTLS</option>
<option value="0">None</option>
</select>
</label>
</div>
</fieldset>
<fieldset>
<fieldset class="form-fieldset">
<legend>SMTP</legend>
<div>
<input required ng-disabled="hasProviderPreset" class="input-text" type="text" ng-model="smtpHost" placeholder="Host" pattern="^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></input>
<input required ng-disabled="hasProviderPreset" class="input-text" type="number" ng-model="smtpPort" placeholder="Port" min="0" max="65535" step="1" pattern="\d+"></input>
<div class="form__row form__row--multi">
<div class="form__col form__col--2">
<input required ng-disabled="hasProviderPreset" class="input-text" type="text"
ng-model="smtpHost" placeholder="Host"
pattern="^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">
</div>
<label>
<select class="input-text" required ng-disabled="hasProviderPreset" ng-model="smtpEncryption">
<div class="form__col">
<input required ng-disabled="hasProviderPreset" class="input-text" type="number"
ng-model="smtpPort" placeholder="Port" min="0" max="65535" step="1" pattern="\d+">
</div>
</div>
<div class="form__row">
<label class="input-select">
<select required ng-disabled="hasProviderPreset" ng-model="smtpEncryption">
<option value="" disabled selected style="display:none">Encryption method</option>
<option value="2">TLS</option>
<option value="1">STARTTLS</option>
<option value="0">None</option>
</select>
</label>
</fieldset>
</div><!--/.details-->
<div class="working" ng-show="busy">
<span class="spinner"></span>
</div>
<div>
</fieldset>
</div>
<div class="spinner-block" ng-show="busy">
<span class="spinner spinner--big"></span>
</div>
<div class="form__row">
<button type="submit" ng-disabled="form.$invalid" ng-click="test()" class="btn">Login</button>
</div>
</form>
</div><!--/.content-->
</div>
</main>
<div ng-include="'tpl/page-footer.html'"></div>
</div>
</section>

View File

@ -1,9 +1,13 @@
<div class="view-login u-waiting-cursor">
<div class="logo">
<section class="page">
<div class="page__canvas">
<header class="page__header">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</div><!--/logo-->
<span class="spinner"></span>
</div>
</header>
<main class="page__main">
<div class="spinner-block">
<span class="spinner spinner--big"></span>
</div>
</main>
<div ng-include="tpl/page-footer.html"></div>
</div>
</section>

12
src/tpl/page-footer.html Normal file
View File

@ -0,0 +1,12 @@
<footer class="page__footer">
<nav>
<ul>
<li><a href="https://whiteout.io/imprint.html">Imprint</a></li>
<li><a href="https://whiteout.io/privacy.html">Privacy</a></li>
<li><a href="https://whiteout.io/terms.html">Terms</a></li>
<li><a href="https://github.com/whiteout-io/mail-html5#license">License</a></li>
<li>Version: TODO</li>
</ul>
</nav>
&copy; 2014 Whiteout Networks GmbH
</footer>

View File

@ -1,24 +1,31 @@
<div class="lightbox-body" ng-controller="PrivateKeyUploadCtrl">
<header>
<div class="lightbox__body" ng-controller="PrivateKeyUploadCtrl">
<header class="lightbox__header">
<h2>Setup Key Sync</h2>
<button class="close" wo-touch="state.privateKeyUpload.toggle(false)" data-action="lightbox-close">
<button class="lightbox__close" wo-touch="state.privateKeyUpload.toggle(false)" data-action="lightbox-close">
<svg><use xlink:href="#icon-close" /><title>Close</title></svg>
</button>
</header>
<div class="content">
<div class="dialog view-privatekey-upload">
<div class="lightbox__content">
<div class="step" ng-show="step === 1">
<p>Your keychain code can be used to securely backup and sync your PGP key between devices. This feature is experimental and not recommended for production use. <a href="https://blog.whiteout.io/2014/07/07/secure-pgp-key-sync-a-proposal/" target="_blank">Learn more</a>.</p>
<h2>{{displayedCode}}</h2>
<p>Please write down your keychain code and keep it in a safe place. Whiteout Networks cannot recover a lost code.</p>
<div ng-show="step === 1">
<p class="typo-paragraph">
Your keychain code can be used to securely backup and sync your PGP key between devices.
This feature is experimental and not recommended for production use.
<a href="https://blog.whiteout.io/2014/07/07/secure-pgp-key-sync-a-proposal/" target="_blank">Learn more</a>.
</p>
<p class="typo-paragraph">
<code class="typo-code">{{displayedCode}}</code>
</p>
<p class="typo-paragraph">
Please write down your keychain code and keep it in a safe place. Whiteout Networks cannot recover a lost code.
</p>
</div>
<div class="step" ng-show="step === 2">
<p>Please confirm the keychain code you have written down.</p>
<div ng-show="step === 2">
<p class="typo-paragraph">Please confirm the keychain code you have written down.</p>
<form class="form">
<div class="input-code">
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code0" focus-me="step === 2" focus-next ng-paste="handlePaste($event)"> -
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code1" focus-next> -
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code2" focus-next> -
@ -26,23 +33,26 @@
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code4" focus-next> -
<input type="text" class="input-text" size="4" maxlength="4" ng-model="code5">
</div>
</form>
</div>
<div class="step" ng-show="step === 3">
<p>Please enter a memorable name for this device e.g. "MacBook Work".</p>
<div ng-show="step === 3">
<p class="typo-paragraph">Please enter a memorable name for this device e.g. “MacBook Work”.</p>
<form class="form">
<input type="text" class="input-text" ng-model="deviceName" placeholder="Device name" focus-me="step === 3">
</form>
</div>
<div class="step" ng-show="step === 4">
<div class="working">
<span class="spinner"></span>
</div><!--/.working-->
<div ng-show="step === 4">
<div class="spinner-block" ng-show="busy">
<span class="spinner spinner--big"></span>
</div>
</div>
<div class="control">
</div>
<footer class="lightbox__controls">
<button ng-show="step > 1 && step < 4" class="btn btn--secondary" wo-touch="goBack()">Go back</button>
<button ng-show="step < 4" class="btn" wo-touch="goForward()">Continue</button>
</div>
</div><!-- /.view-privatekey-upload -->
</div><!-- /.content -->
</div><!-- /.lightbox-body -->
</footer>
</div>

View File

@ -1,40 +1,41 @@
<div class="lightbox-body" ng-controller="SetPassphraseCtrl">
<header>
<div class="lightbox__body" ng-controller="SetPassphraseCtrl">
<header class="lightbox__header">
<h2>Set passphrase</h2>
<button class="close" wo-touch="state.setPassphrase.toggle(false)" data-action="lightbox-close">
<button class="lightbox__close" wo-touch="state.setPassphrase.toggle(false)" data-action="lightbox-close">
<svg><use xlink:href="#icon-close" /><title>Close</title></svg>
</button>
</header>
<div class="content">
<div class="dialog view-set-passphrase">
<p>You can set a passphrase to protect your key on disk. This must be entered everytime you start the app.</p>
<div class="lightbox__content">
<p class="typo-paragraph">
You can set a passphrase to protect your key on disk. This must be entered everytime you start the app.
</p>
<table>
<tbody>
<tr>
<td><label>Current passphrase</label></td>
<td><input class="input-text" type="password" ng-model="oldPassphrase" tabindex="1" focus-me="true"></td>
</tr>
<tr>
<td></td>
<td><label class="input-error-message" ng-class="{'passphrase-label-ok': passphraseRating >= 2}">{{passphraseMsg}}</label></td>
</tr>
<tr>
<td class="no-padding"><label>New passphrase</label></td>
<td class="no-padding"><input class="input-text" type="password" ng-model="newPassphrase" ng-change="checkPassphraseQuality()" tabindex="2"></td>
</tr>
<tr>
<td><label>Confirm passphrase</label></td>
<td><input class="input-text" type="password" ng-model="confirmation" ng-class="{'input-text--error': (confirmation || newPassphrase) && confirmation !== newPassphrase}" tabindex="3"></td>
</tr>
</tbody>
</table>
<form class="form" name="form">
<! TODO use error messages -->
<!--<p class="form__error-message" ng-show="errMsg">{{errMsg}}</p>
<p class="form__error-message" ng-show="form.$invalid">Please fill out all required fields!</p>-->
<div class="control">
<button wo-touch="setPassphrase()" class="btn" ng-disabled="(confirmation || newPassphrase) && confirmation !== newPassphrase" tabindex="4">Set passphrase</button>
<div class="form__row">
<input class="input-text" type="password" ng-model="oldPassphrase" placeholder="Current passphrase" tabindex="1" focus-me="true">
</div>
</div><!-- /.view-set-passphrase -->
</div><!-- /.content -->
</div><!-- /.lightbox-body -->
<p class="form__error-message" ng-show="passphraseMsg && passphraseRating < 2">{{passphraseMsg}}</p>
<p class="form__password-strong-message" ng-show="passphraseMsg && passphraseRating >= 2">{{passphraseMsg}}</p>
<div class="form__row form__row--multi">
<div class="form__col">
<input class="input-text" type="password" ng-model="newPassphrase"
placeholder="New passphrase" ng-change="checkPassphraseQuality()" tabindex="2">
</div>
<div class="form__col">
<input class="input-text" type="password" ng-model="confirmation" placeholder="Confirm passphrase"
ng-class="{'input-text--error': (confirmation || newPassphrase) && confirmation !== newPassphrase}" tabindex="3">
</div>
</div>
</form>
</div>
<footer class="lightbox__controls">
<button wo-touch="setPassphrase()" class="btn" ng-disabled="(confirmation || newPassphrase) && confirmation !== newPassphrase" tabindex="4">Set passphrase</button>
</footer>
</div>

View File

@ -0,0 +1,24 @@
<section class="page">
<div class="page__canvas">
<header class="page__header">
<img src="img/whiteout_logo.svg" alt="whiteout.io">
</header>
<main class="page__main">
<h2 class="typo-title">Validate phone number</h2>
<p class="typo-paragraph">We have sent you a validation code via SMS. Please enter this code to confirm your phone number.</p>
<form class="form" name="formValidate">
<p class="form__error-message" ng-show="errMsgValidate">{{errMsgValidate}}</p>
<div class="form__row">
<input type="text" class="input-text input-text--big" size="6" maxlength="6" ng-model="token" placeholder="Code" focus-me="step === 3" required pattern="([a-zA-Z0-9]*)">
</div>
<div class="spinner-block" ng-show="busyValidate">
<span class="spinner spinner--big"></span>
</div>
<div class="form__row">
<button class="btn btn--big" type="submit" ng-click="validateUser()">Confirm code</button>
</div>
</form>
</main>
<div ng-include="'tpl/page-footer.html'"></div>
</div>
</section>

View File

@ -1,11 +1,11 @@
<div class="lightbox-body" ng-controller="WriteCtrl">
<header>
<div class="lightbox__body" ng-controller="WriteCtrl">
<header class="lightbox__header">
<h2>{{writerTitle}}</h2>
<button class="close" wo-touch="state.writer.close()" data-action="lightbox-close">
<button class="lightbox__close" wo-touch="state.writer.close()" data-action="lightbox-close">
<svg><use xlink:href="#icon-close" /><title>Close</title></svg>
</button>
</header>
<div class="content write">
<div class="lightbox__content write">
<header class="write__header">
<div class="mail-addresses" focus-input="state.lightbox === 'write' && writerTitle !== 'Reply'"
@ -70,5 +70,5 @@
<button wo-touch="sendToOutbox()" class="btn" ng-class="{'btn--invalid': sendBtnSecure === false}" ng-disabled="!okToSend" tabindex="4">{{sendBtnText || 'Send'}}</button>
</div>
</div><!--/.content-->
</div><!--/.lightbox-body-->
</div>
</div>