Revamp mobile including CSS flexbox for messageListItem

This commit is contained in:
djmaze 2021-02-15 15:20:22 +01:00
parent 6238b97f08
commit 10f9ce39d9
70 changed files with 479 additions and 821 deletions

View file

@ -4,7 +4,8 @@ import {
doc,
$htmlCL,
leftPanelDisabled,
Settings
Settings,
isMobile
} from 'Common/Globals';
import { KeyState } from 'Common/Enums';
@ -48,7 +49,7 @@ export class AbstractApp {
* @returns {boolean}
*/
download(link) {
if (Settings.app('mobile')) {
if (isMobile()) {
open(link, '_self');
focus();
} else {
@ -82,8 +83,7 @@ export class AbstractApp {
}
bootstart() {
const mobile = Settings.app('mobile'),
register = (key, ClassObject, templateID) => ko.components.register(key, {
const register = (key, ClassObject, templateID) => ko.components.register(key, {
template: { element: templateID || (key + 'Component') },
viewModel: {
createViewModel: (params, componentInfo) => {
@ -110,7 +110,7 @@ export class AbstractApp {
register('Select', SelectComponent);
register('TextArea', TextAreaComponent);
register('CheckboxSimple', CheckboxComponent, 'CheckboxComponent');
if (mobile || !Settings.app('materialDesign')) {
if (isMobile() || !Settings.app('materialDesign')) {
register('Checkbox', CheckboxComponent);
} else {
register('Checkbox', CheckboxMaterialDesignComponent, 'CheckboxMaterialDesignComponent');
@ -118,7 +118,7 @@ export class AbstractApp {
initOnStartOrLangChange();
if (mobile) {
if (isMobile()) {
leftPanelDisabled(true);
} else {
window.addEventListener('resize', () => leftPanelDisabled(767 >= window.innerWidth));

View file

@ -17,7 +17,7 @@ import {
ClientSideKeyName
} from 'Common/EnumsUser';
import { doc, createElement, $htmlCL, Settings, leftPanelDisabled } from 'Common/Globals';
import { doc, createElement, $htmlCL, Settings, leftPanelDisabled, isMobile } from 'Common/Globals';
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
@ -871,12 +871,11 @@ class AppUser extends AbstractApp {
}
}
initVerticalLayoutResizer(sClientSideKeyName) {
initVerticalLayoutResizer() {
const left = doc.getElementById('rl-left'),
right = doc.getElementById('rl-right'),
fDisable = bDisable => {
this.setLayoutResizer(left, right, sClientSideKeyName, bDisable ? null : 'width');
};
fDisable = bDisable =>
this.setLayoutResizer(left, right, ClientSideKeyName.FolderListSize, bDisable ? null : 'width');
if (left && right) {
fDisable(false);
leftPanelDisabled.subscribe(value => fDisable(value));
@ -1023,8 +1022,8 @@ class AppUser extends AbstractApp {
}, 500);
}
if (!Settings.app('mobile')) {
setTimeout(() => this.initVerticalLayoutResizer(ClientSideKeyName.FolderListSize), 1);
if (!isMobile()) {
setTimeout(() => this.initVerticalLayoutResizer(), 1);
}
} else {
this.logout();

View file

@ -7,6 +7,9 @@ export const $htmlCL = doc.documentElement.classList;
export const Settings = rl.settings;
/** @media screen and (max-width: 600px) { */
export const isMobile = () => $htmlCL.contains('rl-mobile'); // || rl.settings.app('mobile')
export const dropdownVisibility = ko.observable(false).extend({ rateLimit: 0 });
export const moveAction = ko.observable(false);

View file

@ -2,7 +2,7 @@ import 'External/ko';
import ko from 'ko';
import { HtmlEditor } from 'Common/Html';
import { timeToNode } from 'Common/Momentor';
import { doc } from 'Common/Globals';
import { doc, isMobile } from 'Common/Globals';
import { EmailAddressesComponent } from 'Component/EmailAddresses';
const rlContentType = 'snappymail/action',
@ -86,7 +86,7 @@ ko.bindingHandlers.emailsTags = {
// Start dragging selected messages
ko.bindingHandlers.dragmessages = {
init: (element, fValueAccessor) => {
if (!rl.settings.app('mobile')) {
if (!isMobile()) {
element.addEventListener("dragstart", e => {
let data = fValueAccessor()(e);
dragImage || (dragImage = doc.getElementById('messagesDragImage'));
@ -119,7 +119,7 @@ ko.bindingHandlers.dragmessages = {
// Drop selected messages on folder
ko.bindingHandlers.dropmessages = {
init: (element, fValueAccessor) => {
if (!rl.settings.app('mobile')) {
if (!isMobile()) {
const folder = fValueAccessor(),
// folder = ko.dataFor(element),
fnStop = e => {

View file

@ -1,6 +1,6 @@
import ko from 'ko';
import { doc, $htmlCL } from 'Common/Globals';
import { doc, $htmlCL/*, isMobile*/ } from 'Common/Globals';
import { isNonEmptyArray } from 'Common/Utils';
let currentScreen = null,
@ -9,7 +9,7 @@ let currentScreen = null,
const SCREENS = {},
autofocus = dom => {
// if (!rl.settings.app('mobile')) {
// if (!isMobile()) {
const af = dom.querySelector('[autofocus]');
af && af.focus();
};

View file

@ -44,8 +44,6 @@ export class MessageModel extends AbstractModel {
this.addObservables({
subject: '',
subjectPrefix: '',
subjectSuffix: '',
size: 0,
dateTimeStampInUTC: 0,
priority: MessagePriority.Normal,
@ -117,8 +115,6 @@ export class MessageModel extends AbstractModel {
clear() {
this._reset();
this.subject('');
this.subjectPrefix('');
this.subjectSuffix('');
this.size(0);
this.dateTimeStampInUTC(0);
this.priority(MessagePriority.Normal);
@ -192,14 +188,6 @@ export class MessageModel extends AbstractModel {
json.Priority = MessagePriority.High == p || MessagePriority.Low == p ? p : MessagePriority.Normal;
}
if (super.revivePropertiesFromJson(json)) {
if (isArray(json.SubjectParts)) {
this.subjectPrefix(json.SubjectParts[0]);
this.subjectSuffix(json.SubjectParts[1]);
} else {
this.subjectPrefix('');
this.subjectSuffix(this.subject());
}
// this.foundedCIDs = isArray(json.FoundedCIDs) ? json.FoundedCIDs : [];
// this.attachments(AttachmentCollectionModel.reviveFromJson(json.Attachments, this.foundedCIDs));
@ -454,9 +442,6 @@ export class MessageModel extends AbstractModel {
this.checked(message.checked());
this.hasAttachments(message.hasAttachments());
this.attachmentsSpecData(message.attachmentsSpecData());
this.subjectPrefix(this.subjectPrefix());
this.subjectSuffix(this.subjectSuffix());
}
this.body = null;

View file

@ -1,6 +1,6 @@
import { Capa } from 'Common/Enums';
import { Focused, ClientSideKeyName } from 'Common/EnumsUser';
import { doc, leftPanelDisabled, leftPanelType, moveAction, Settings } from 'Common/Globals';
import { doc, leftPanelDisabled, leftPanelType, moveAction, Settings, isMobile } from 'Common/Globals';
import { pString, pInt } from 'Common/Utils';
import { getFolderFromCacheList, getFolderFullNameRaw, getFolderInboxName } from 'Common/Cache';
import { i18n } from 'Common/Translator';
@ -56,7 +56,7 @@ export class MailBoxUserScreen extends AbstractScreen {
AppStore.focusedState(Focused.None);
AppStore.focusedState(Focused.MessageList);
if (Settings.app('mobile')) {
if (isMobile()) {
leftPanelDisabled(true);
}
@ -117,7 +117,7 @@ export class MailBoxUserScreen extends AbstractScreen {
* @returns {void}
*/
onBuild() {
if (!Settings.app('mobile')) {
if (!isMobile()) {
setTimeout(() =>
rl.app.initHorizontalLayoutResizer(ClientSideKeyName.MessageListSize)
, 1);

View file

@ -1,5 +1,5 @@
import { Capa, KeyState } from 'Common/Enums';
import { keyScope, leftPanelType, leftPanelDisabled, Settings } from 'Common/Globals';
import { keyScope, leftPanelType, leftPanelDisabled, Settings, isMobile } from 'Common/Globals';
import { runSettingsViewModelHooks } from 'Common/Plugins';
import { initOnStartOrLangChange, i18n } from 'Common/Translator';
@ -104,7 +104,7 @@ export class SettingsUserScreen extends AbstractSettingsScreen {
keyScope(KeyState.Settings);
leftPanelType('');
if (Settings.app('mobile')) {
if (isMobile()) {
leftPanelDisabled(true);
}
}

View file

@ -1,4 +1,5 @@
import ko from 'ko';
import { isMobile } from 'Common/Globals';
export const ThemeStore = {
themes: ko.observableArray(),
@ -11,8 +12,10 @@ export const ThemeStore = {
this.themes(Array.isArray(themes) ? themes : []);
this.theme(Settings.get('Theme'));
this.themeBackgroundName(Settings.get('UserBackgroundName'));
this.themeBackgroundHash(Settings.get('UserBackgroundHash'));
if (!isMobile()) {
this.themeBackgroundName(Settings.get('UserBackgroundName'));
this.themeBackgroundHash(Settings.get('UserBackgroundHash'));
}
}
};

View file

@ -2,7 +2,7 @@ import ko from 'ko';
import { KeyState } from 'Common/Enums';
import { Focused } from 'Common/EnumsUser';
import { keyScope, leftPanelDisabled, Settings } from 'Common/Globals';
import { keyScope, leftPanelDisabled, Settings, isMobile } from 'Common/Globals';
class AppUserStore {
constructor() {
@ -22,27 +22,19 @@ class AppUserStore {
contactsIsAllowed: false
});
const isMobile = Settings.app('mobile');
this.focusedState.subscribe((value) => {
this.focusedState.subscribe(value => {
switch (value) {
case Focused.MessageList:
keyScope(KeyState.MessageList);
if (isMobile) {
leftPanelDisabled(true);
}
isMobile() && leftPanelDisabled(true);
break;
case Focused.MessageView:
keyScope(KeyState.MessageView);
if (isMobile) {
leftPanelDisabled(true);
}
isMobile() && leftPanelDisabled(true);
break;
case Focused.FolderList:
keyScope(KeyState.FolderList);
if (isMobile) {
leftPanelDisabled(false);
}
isMobile() && leftPanelDisabled(false);
break;
default:
break;

View file

@ -1,7 +1,7 @@
import ko from 'ko';
import { StorageResultType, Notification } from 'Common/Enums';
import { Layout, Focused, MessageSetAction } from 'Common/EnumsUser';
import { Focused, MessageSetAction } from 'Common/EnumsUser';
import { doc } from 'Common/Globals';
import { pInt, pString } from 'Common/Utils';
import { plainToHtml } from 'Common/UtilsUser';
@ -211,7 +211,7 @@ class MessageUserStore {
this.message.subscribe(message => {
if (message) {
if (Layout.NoPreview === SettingsStore.layout()) {
if (!SettingsStore.usePreviewPane()) {
AppStore.focusedState(Focused.MessageView);
}
} else {

View file

@ -3,7 +3,7 @@ import ko from 'ko';
import { MESSAGES_PER_PAGE_VALUES } from 'Common/Consts';
import { Layout, EditorDefaultType } from 'Common/EnumsUser';
import { pInt } from 'Common/Utils';
import { doc } from 'Common/Globals';
import { doc, isMobile } from 'Common/Globals';
class SettingsUserStore {
constructor() {
@ -34,7 +34,7 @@ class SettingsUserStore {
autoLogout: 30
});
this.usePreviewPane = ko.computed(() => Layout.NoPreview !== this.layout());
this.usePreviewPane = ko.computed(() => Layout.NoPreview !== this.layout() && !isMobile());
this.subscribers();
}
@ -42,9 +42,9 @@ class SettingsUserStore {
subscribers() {
const htmlCL = doc.documentElement.classList;
this.layout.subscribe(value => {
htmlCL.toggle('rl-no-preview-pane', Layout.NoPreview === value);
htmlCL.toggle('rl-side-preview-pane', Layout.SidePreview === value);
htmlCL.toggle('rl-bottom-preview-pane', Layout.BottomPreview === value);
htmlCL.toggle('rl-no-preview-pane', isMobile() || Layout.NoPreview === value);
htmlCL.toggle('rl-side-preview-pane', !isMobile() && Layout.SidePreview === value);
htmlCL.toggle('rl-bottom-preview-pane', !isMobile() && Layout.BottomPreview === value);
dispatchEvent(new CustomEvent('rl-layout', {detail:value}));
});
}
@ -58,7 +58,7 @@ class SettingsUserStore {
this.messagesPerPage(settingsGet('MPP'));
this.showImages(!!settingsGet('ShowImages'));
this.useCheckboxesInList(!!settingsGet('UseCheckboxesInList'));
this.useCheckboxesInList(!!(isMobile() || settingsGet('UseCheckboxesInList')));
this.allowDraftAutosave(!!settingsGet('AllowDraftAutosave'));
this.useThreads(!!settingsGet('UseThreads'));
this.replySameFolder(!!settingsGet('ReplySameFolder'));

View file

@ -26,16 +26,6 @@
100% {transform: translateX(0)}
}
html.rl-started-trigger.no-mobile .b-login-content .loginFormWrapper {
/*transform: scale(1.1);*/
transform: translateY(-20px);
opacity: 0.5;
}
/*html.rl-started-trigger.no-mobile #rl-content {
opacity: 0.7;
}*/
html.rl-started-delay {
#rl-left {
@ -56,97 +46,105 @@ html.rl-started-delay {
}
html {
&.rgba.backgroundsize .e-strip-animation {
.e-strip-animation {
background-size: 60px 60px;
.rl-strip-animation(0, 0.1);
animation: animate-stripes 2s linear infinite;
}
}
html.no-mobile {
@media screen and (min-width: 1000px) {
.b-login-content {
.alertError {
display: block;
opacity: 1;
transition: opacity 0.5s linear;
html.rl-started-trigger .b-login-content .loginFormWrapper {
/*transform: scale(1.1);*/
transform: translateY(-20px);
opacity: 0.5;
}
html {
.b-login-content {
.alertError {
display: block;
opacity: 1;
transition: opacity 0.5s linear;
}
.alertError[hidden] {
opacity: 0;
}
}
.alertError[hidden] {
.b-login-content .errorAnimated {
animation: login-form-shake 400ms ease-in-out;
}
.b-login-content .errorAnimated .buttonLogin {
color: #b94a48;
font-weight: bold;
}
.b-login-content .afterLoginHide {
opacity: 0;
}
}
.b-login-content .errorAnimated {
animation: login-form-shake 400ms ease-in-out;
}
.b-login-content .errorAnimated .buttonLogin {
color: #b94a48;
font-weight: bold;
}
.b-login-content .afterLoginHide {
opacity: 0;
}
.b-login-content .loginFormWrapper {
transition: all 0.3s ease-out;
}
& .button-delete-transitions {
transition: all 0.2s linear;
}
& .b-folders .e-item .anim-action-class {
animation: highlight-folder-row 0.5s linear;
}
& .b-folders .btn.buttonContacts {
transition: margin 0.3s linear;
}
& .b-folders .b-content.opacity-on-panel-disabled {
transition: opacity 0.3s linear;
}
& .messageList {
.messageListItem {
transition: max-height 400ms ease;
.b-login-content .loginFormWrapper {
transition: all 0.3s ease-out;
}
.listDragOver {
transition: all 400ms ease;
& .button-delete-transitions {
transition: all 0.2s linear;
}
}
& .b-list-content {
.e-contact-item {
transition: max-height 400ms ease;
& .b-folders .e-item .anim-action-class {
animation: highlight-folder-row 0.5s linear;
}
}
& .modal.b-domain-content {
.modal-body {
transition: left 500ms ease;
& .b-folders .btn.buttonContacts {
transition: margin 0.3s linear;
}
}
#rl-popups > .rl-view-model .modal {
transition: all .2s ease-out;
}
#rl-popups > .rl-view-model:not(.show) .modal {
top: -25%;
}
#rl-popups > .rl-view-model .modal.fade {
opacity: 1;
}
#rl-popups > .rl-view-model:not(.show) .modal.fade {
opacity: 0;
}
& .b-folders .b-content.opacity-on-panel-disabled {
transition: opacity 0.3s linear;
}
& .b-compose.loading .b-header-toolbar {
background-size: 60px 60px;
.rl-strip-animation(255, 0.2);
animation: animate-stripes 2s linear infinite;
& .messageList {
.messageListItem {
transition: max-height 400ms ease;
}
.listDragOver {
transition: all 400ms ease;
}
}
& .b-list-content {
.e-contact-item {
transition: max-height 400ms ease;
}
}
& .modal.b-domain-content {
.modal-body {
transition: left 500ms ease;
}
}
#rl-popups > .rl-view-model .modal {
transition: all .2s ease-out;
}
#rl-popups > .rl-view-model:not(.show) .modal {
top: -25%;
}
#rl-popups > .rl-view-model .modal.fade {
opacity: 1;
}
#rl-popups > .rl-view-model:not(.show) .modal.fade {
opacity: 0;
}
& .b-compose.loading .b-header-toolbar {
background-size: 60px 60px;
.rl-strip-animation(255, 0.2);
animation: animate-stripes 2s linear infinite;
}
}
}

View file

@ -90,10 +90,8 @@
background-image: none;
background: rgba(0, 0, 0, .5) !important;
.attachmentIcon {
color: #fff;
text-shadow: 0 1px 0 #000;
}
color: #fff;
text-shadow: 0 1px 0 #000;
}
}

View file

@ -112,10 +112,7 @@
&.hideContactListCheckbox {
.checkboxItem {
display: none !important;
}
.sidebarParent {
margin-right: 10px !important;
visibility: hidden;
}
}
@ -132,32 +129,13 @@
cursor: pointer;
margin: 0;
border: 0 solid transparent;
border: 0;
border-left: 6px solid #eee;
z-index: 100;
border-bottom: 1px solid #ddd;
.delimiter {
position: relative;
display: block;
height: 1px;
background-color: #999;
opacity: 0.2;
}
.wrapper {
padding: 0;
}
.sidebarParent {
display: inline-block;
width: 6px;
background-color: #eee;
float: left;
height: 100%;
}
&.focused .sidebarParent {
background-color: #bbb;
&.focused {
border-left-color: #bbb;
}
&.deleted {
@ -197,28 +175,22 @@
}
&.checked {
border-left-color: #69A8F5;
z-index: 101;
.sidebarParent {
background-color: #69A8F5;
}
&.focused .sidebarParent {
background-color: darken(#69A8F5, 5%) !important;
&.focused {
border-left-color: darken(#69A8F5, 5%);
}
}
&.selected {
background-color: #fff;
border-left-color: #398CF2;
z-index: 102;
.sidebarParent {
background-color: #398CF2;
}
&.focused .sidebarParent {
background-color: darken(#398CF2, 5%) !important;
&.focused {
border-left-color: darken(#398CF2, 5%);
}
}
}
@ -394,7 +366,7 @@
cursor: pointer;
margin: 0;
border: 0 solid transparent;
border: 0;
z-index: 100;
border-bottom: 1px solid #ddd;
}

View file

@ -389,7 +389,8 @@ html.rl-bottom-preview-pane {
}
}
html.rl-mobile .hide-on-mobile {
html.rl-mobile .hide-mobile,
html:not(.rl-mobile) .show-mobile {
display: none !important;
}

View file

@ -168,6 +168,7 @@
.language-button {
padding: 5px;
outline: none;
text-decoration: none;
}
.e-mobile-switcher {

View file

@ -14,8 +14,7 @@ html, body {
}
body {
background-color: var(--main-bg-color, #e3e3e3);
background-size: var(--main-bg-size);
background: var(--main-bg-color, #e3e3e3);
color: var(--main-color, #333);
-webkit-touch-callout: none;
@ -28,11 +27,13 @@ body {
}
/*
.rl-mobile / .no-mobile
.rl-mobile
*/
@media screen and (min-width: 1000px) {
body {
background-image: var(--main-bg-image);
background-size: var(--main-bg-size);
background-repeat: var(--main-bg-repeat);
}
}

View file

@ -183,19 +183,6 @@ html.rl-no-preview-pane {
text-align: center;
}
.delimiter {
display: block;
height: 1px;
background-color: #e5e5e5;
}
.messageListItem:last-child {
border-bottom: 1px solid #e5e5e5;
&.selected {
border-bottom: 1px solid #bfd5ef;
}
}
.fullThreadsParent {
height: 25px;
padding: 3px 5px;
@ -206,49 +193,24 @@ html.rl-no-preview-pane {
.messageListItem {
position: relative;
height: 52px;
max-height: 60px;
font-size: 12px;
line-height: 21px;
overflow: hidden;
cursor: pointer;
margin: 0;
border: 0 solid transparent;
padding: 5px 0;
border: 0;
border-bottom: 1px solid rgba(153, 153, 153, 0.2);
border-left: 6px solid #eee;
z-index: 100;
background-color: #f9f9f9;
/* &:nth-child(even) {
background-color: #f3f3f3;
}*/
.delimiter {
position: relative;
display: block;
height: 1px;
background-color: #999;
opacity: 0.2;
}
.wrapper {
padding: 5px 0;
}
.sidebarParent {
display: inline-block;
width: 6px;
background-color: #eee;
float: left;
height: 100%;
}
&.focused {
background-color: #f5f5f5;
}
&.focused .sidebarParent {
background-color: #ccc !important;
border-left-color: #ccc;
}
.importantMark {
@ -260,7 +222,7 @@ html.rl-no-preview-pane {
&.deleted-mark {
opacity: .7;
.sender, .subject, .subject-prefix, .subject-suffix {
.subjectParent {
text-decoration: line-through;
}
}
@ -269,15 +231,6 @@ html.rl-no-preview-pane {
display: inline;
}
&.e-single-line {
height: 35px;
}
&.e-single-line .wrapper {
line-height: 25px;
padding: 5px;
}
&.new {
max-height: 0;
}
@ -288,62 +241,36 @@ html.rl-no-preview-pane {
}
.checkboxMessage {
display: inline-block;
float: left;
margin-top: 11px;
padding: 0 8px 0 6px;
font-size: 16px;
}
&.e-single-line .checkboxMessage {
margin-top: 1px;
}
.flagParent {
display: inline-block;
float: right;
padding: 0 10px 0 5px;
}
&.e-single-line .flagParent {
float: left;
padding: 0 8px 0 2px;
}
.dateParent {
display: inline-block;
float: right;
position: relative;
time {
margin: 0 5px;
color: #999;
font-size: 11px;
}
&.e-single-line .dateParent {
white-space: nowrap;
}
.threadsParent {
display: inline-block;
float: right;
position: relative;
}
.attachmentParent {
display: inline-block;
float: right;
position: relative;
margin: 2px 10px 0 5px;
}
&.e-single-line .attachmentParent {
float: left;
margin: 0 8px 0 0;
color: #666;
text-shadow: 0 1px 0 #eee;
}
.senderParent {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.threadsCountParent {
@ -366,25 +293,10 @@ html.rl-no-preview-pane {
border-color: #666;
}
&.e-single-line .senderParent {
display: inline-block;
text-overflow: none;
width: 200px;
float: left;
font-weight: normal;
}
.subjectParent {
display: block;
color: #000;
overflow: hidden;
text-overflow: ellipsis;
color: #000;
}
&.e-single-line .subjectParent {
}
.senderParent, .subjectParent, .dateParent {
white-space: nowrap;
}
@ -395,7 +307,7 @@ html.rl-no-preview-pane {
}
&.emptySubject .subjectParent {
.subject, .subject-prefix, .subject-suffix {
.subject {
display: none;
}
.emptySubjectText {
@ -403,7 +315,8 @@ html.rl-no-preview-pane {
}
}
.sender, .subject, .subject-suffix {
.sender, .subject {
margin-left: 0;
overflow: hidden;
text-overflow: ellipsis;
}
@ -432,20 +345,6 @@ html.rl-no-preview-pane {
}
}
.subject-prefix {
color: #888;
/*font-style: italic;*/
}
.attachment {
display: none;
}
.flagOff, .flagOn, .flagOnHalf {
cursor: pointer;
display: inline-block;
}
.flagOff {
opacity: 0.5;
&:hover {
@ -454,12 +353,12 @@ html.rl-no-preview-pane {
}
.flagOn, .flagOnHalf {
display: none;
color: orange;
}
.replyFlag, .forwardFlag {
display: none;
margin-right: 0.25em;
}
&.answered .replyFlag {
@ -470,81 +369,53 @@ html.rl-no-preview-pane {
display: inline-block;
}
&.withAttachments .attachment {
display: inline-block;
color: #666;
text-shadow: 0 1px 0 #eee;
&:not(.withAttachments) .attachmentParent {
display: none;
}
&.hasUnseenSubMessage {
background-color: #FFFFD9;
.sidebarParent {
background-color: lighten(orange, 30%);
}
&.focused .sidebarParent {
background-color: darken(orange, 10%) !important;
border-left-color: lighten(orange, 30%);
&.focused {
border-left-color: darken(orange, 10%);
}
}
&.unseen {
background-color: #FFFFD9;
.sender, .subject, .subject-suffix {
border-left-color: orange;
.sender, .subjectParent {
font-weight: bold;
}
.sidebarParent {
background-color: orange;
}
&.focused .sidebarParent {
background-color: darken(orange, 10%) !important;
&.focused {
border-left-color: darken(orange, 10%);
}
}
&.checked {
.sidebarParent {
background-color: lighten(#398CF2, 10%) !important;
}
border-left-color: lighten(#398CF2, 10%);
&.focused .sidebarParent {
background-color: darken(#398CF2, 5%) !important;
&.focused {
border-left-color: darken(#398CF2, 5%);
}
}
&.selected {
background-color: #DFEFFF;
border-bottom-color: rgba(57, 140, 242, 0.2);
border-left-color: #398CF2;
z-index: 101;
.sidebarParent {
background-color: #398CF2 !important;
}
.delimiter {
background-color: #398CF2;
opacity: 0.2;
}
+ .messageListItem .delimiter {
background-color: #398CF2;
opacity: 0.3;
+ .messageListItem {
border-bottom-color: rgba(57, 140, 242, 0.3);
}
}
&.hasFlaggedSubMessage {
.flagOff, .flagOn {
display: none;
}
.flagOnHalf {
display: inline-block;
}
}
&.flagged {
.flagOff, .flagOnHalf {
display: none;
}
.flagOn {
display: inline-block;
}
&:not(.flagged) .flagOn,
&:not(.hasFlaggedSubMessage) .flagOnHalf,
&.flagged .flagOff, &.hasFlaggedSubMessage .flagOff {
display: none;
}
}
}
@ -560,10 +431,7 @@ html.rl-no-preview-pane {
&.hideMessageListCheckbox {
.checkboxMessage, .checkboxCheckAll {
display: none !important;
}
.sidebarParent {
margin-right: 10px !important;
visibility: hidden;
}
}
}
@ -572,7 +440,7 @@ html.rl-no-preview-pane {
@media screen and (min-width: 1401px) {
.messageList .b-content .messageListItem {
font-size: 13px;
.dateParent {
time {
font-size: 13px;
}
}
@ -598,3 +466,76 @@ html.rl-mobile {
width: 160px !important;
}
}
.messageListItem {
display: flex;
flex-wrap: wrap;
> * {
display: flex;
flex: 0 0 auto;
order: 0;
}
}
.rl-side-preview-pane, .rl-mobile {
.messageListItem {
.checkboxMessage {
margin: 10px 0 -5px;
}
.subjectParent {
flex: 1 0 auto;
margin-left: 30px;
order: 1;
width: calc(100% - 60px);
}
.senderParent {
flex: 1 0 auto;
}
.flagParent {
order: 1;
}
.attachmentParent {
order: 2;
}
}
}
html:not(.rl-mobile):not(.rl-side-preview-pane) .messageList {
.messageListItem {
line-height: 25px;
flex-wrap: nowrap;
.checkboxMessage {
line-height: 25px;
}
.flagParent {
margin-top: 6px;
}
.attachmentParent {
margin: 6px 8px 0 0;
}
.senderParent {
font-weight: normal;
text-overflow: none;
flex: 0 0 25%;
}
.subjectParent {
flex: 1 1 auto;
}
}
}

View file

@ -125,7 +125,6 @@ html.rl-no-preview-pane {
.messageItemHeader {
position: absolute;
padding: 10px;
background-color: #f8f8f8;
border-top: 0;
@ -133,12 +132,6 @@ html.rl-no-preview-pane {
border-top-right-radius: 5px;
border-top-left-radius: 5px;
z-index: 1;
top: 0;
left: 0;
right: 0;
.date {
}
.subjectParent {
font-size: 18px;
@ -157,9 +150,7 @@ html.rl-no-preview-pane {
}
.informationShort {
margin: 4px 0;
margin-left: 5px;
margin-right: 50px;
margin: 4px 50px 0 5px;
a {
.g-ui-link;

View file

@ -169,7 +169,3 @@ textarea + .settings-save-trigger {
.list-table {
max-width: 800px;
}
html.mobile .hide-mobile {
display:none;
}

View file

@ -12,11 +12,7 @@ class LoginAdminView extends AbstractViewCenter {
constructor() {
super('Admin/Login', 'AdminLogin');
const appSettingsGet = rl.settings.app;
this.mobile = !!appSettingsGet('mobile');
this.mobileDevice = !!appSettingsGet('mobileDevice');
this.hideSubmitButton = appSettingsGet('hideSubmitButton');
this.hideSubmitButton = rl.settings.app('hideSubmitButton');
this.addObservables({
login: '',

View file

@ -1090,7 +1090,7 @@ class ComposePopupView extends AbstractViewPopup {
}
setFocusInPopup() {
// rl.settings.app('mobile') ||
// isMobile() ||
setTimeout(() => {
if (!this.to()) {
this.to.focused(true);

View file

@ -160,7 +160,7 @@ class FilterPopupView extends AbstractViewPopup {
}
onShowWithDelay() {
if (this.isNew() && this.filter()/* && !rl.settings.app('mobile')*/) {
if (this.isNew() && this.filter()/* && !isMobile()*/) {
this.filter().nameFocused(true);
}
}

View file

@ -72,7 +72,7 @@ class FolderCreatePopupView extends AbstractViewPopup {
}
onShowWithDelay() {
// rl.settings.app('mobile') ||
// isMobile() ||
this.folderNameFocused(true);
}
}

View file

@ -166,7 +166,7 @@ class IdentityPopupView extends AbstractViewPopup {
}
onShowWithDelay() {
if (!this.owner()/* && !rl.settings.app('mobile')*/) {
if (!this.owner()/* && !isMobile()*/) {
this.emailFocused(true);
}
}

View file

@ -49,7 +49,7 @@ class TwoFactorTestPopupView extends AbstractViewPopup {
}
onShowWithDelay() {
// rl.settings.app('mobile') ||
// isMobile() ||
this.codeFocused(true);
}
}

View file

@ -18,9 +18,6 @@ export class AbstractSystemDropDownUserView extends AbstractViewRight {
constructor(name) {
super(name, 'SystemDropDown');
this.mobile = !!Settings.app('mobile');
this.mobileDevice = !!Settings.app('mobileDevice');
this.allowSettings = !!Settings.capa(Capa.Settings);
this.allowHelp = !!Settings.capa(Capa.Help);

View file

@ -69,9 +69,6 @@ class LoginUserView extends AbstractViewCenter {
signMeType: LoginSignMeType.Unused
});
this.mobile = !!Settings.app('mobile');
this.mobileDevice = !!Settings.app('mobileDevice');
this.forgotPasswordLinkUrl = Settings.app('forgotPasswordLinkUrl');
this.registrationLinkUrl = Settings.app('registrationLinkUrl');

View file

@ -1,8 +1,8 @@
import ko from 'ko';
import { Capa, KeyState } from 'Common/Enums';
import { Focused, Layout } from 'Common/EnumsUser';
import { leftPanelDisabled, moveAction, Settings } from 'Common/Globals';
import { Focused } from 'Common/EnumsUser';
import { leftPanelDisabled, moveAction, Settings, isMobile } from 'Common/Globals';
import { mailBox, settings } from 'Common/Links';
import { setFolderHash } from 'Common/Cache';
@ -54,12 +54,9 @@ export class FolderListMailBoxUserView extends AbstractViewLeft {
onBuild(dom) {
const qs = s => dom.querySelector(s),
eqs = (ev, s) => ev.target.closestWithin(s, dom),
isMobile = Settings.app('mobile'),
fSelectFolder = (el, event, starred) => {
const isMove = moveAction();
if (isMobile) {
leftPanelDisabled(true);
}
isMobile() && leftPanelDisabled(true);
event.preventDefault();
@ -78,7 +75,7 @@ export class FolderListMailBoxUserView extends AbstractViewLeft {
event.ctrlKey
);
} else {
if (Layout.NoPreview === SettingsStore.layout()) {
if (!SettingsStore.usePreviewPane()) {
MessageStore.message(null);
}

View file

@ -7,7 +7,6 @@ import {
} from 'Common/Enums';
import {
Layout,
Focused,
ComposeType,
FolderType,
@ -16,7 +15,7 @@ import {
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { doc, leftPanelDisabled, moveAction, Settings } from 'Common/Globals';
import { doc, leftPanelDisabled, moveAction, Settings, isMobile } from 'Common/Globals';
import { computedPaginatorHelper } from 'Common/UtilsUser';
import { File } from 'Common/File';
@ -61,7 +60,6 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
this.iGoToUpUpOrDownDownTimeout = 0;
this.mobile = !!Settings.app('mobile');
this.newMoveToFolder = !!Settings.get('NewMoveToFolder');
this.allowReload = !!Settings.capa(Capa.Reload);
@ -125,11 +123,6 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
this.sLastSearchValue = '';
this.addComputables({
messageListItemTemplate: () =>
this.mobile || Layout.SidePreview === SettingsStore.layout()
? 'MailMessageListItem'
: 'MailMessageListItemNoPreviewPane',
messageListSearchDesc: () => {
const value = MessageStore.messageListEndSearch();
return value ? i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', { 'SEARCH': value }) : ''
@ -179,9 +172,9 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
isUnSpamVisible: () =>
this.isSpamFolder() && !this.isSpamDisabled() && !this.isDraftFolder() && !this.isSentFolder(),
mobileCheckedStateShow: () => this.mobile ? 0 < MessageStore.messageListChecked().length : true,
mobileCheckedStateShow: () => isMobile() ? 0 < MessageStore.messageListChecked().length : true,
mobileCheckedStateHide: () => this.mobile ? !MessageStore.messageListChecked().length : true,
mobileCheckedStateHide: () => isMobile() ? !MessageStore.messageListChecked().length : true,
messageListFocused: () => Focused.MessageList === AppStore.focusedState()
});
@ -388,7 +381,7 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
return false;
});
if (Layout.NoPreview === SettingsStore.layout() && !this.message()) {
if (!SettingsStore.usePreviewPane() && !this.message()) {
this.selector.iFocusedNextHelper = up ? -1 : 1;
} else {
this.selector.iSelectNextHelper = up ? -1 : 1;
@ -405,8 +398,8 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
useAutoSelect() {
return !this.messageListDisableAutoSelect()
&& !/is:unseen/.test(this.mainMessageListSearch())
&& Layout.NoPreview !== SettingsStore.layout();
&& !/is:unseen/.test(this.mainMessageListSearch())
&& SettingsStore.usePreviewPane();
}
searchEnterAction() {
@ -680,7 +673,7 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
this.selector.init(dom.querySelector('.b-content'), KeyState.MessageList);
dom.addEventListener('click', event => {
this.mobile && leftPanelDisabled(true);
isMobile() && leftPanelDisabled(true);
if (eqs(event, '.messageList .b-message-list-wrapper') && Focused.MessageView === AppStore.focusedState()) {
AppStore.focusedState(Focused.MessageList);
@ -706,7 +699,7 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
this.initUploaderForAppend();
this.initShortcuts();
if (!rl.settings.app('mobile') && Settings.capa(Capa.Prefetch)) {
if (!isMobile() && Settings.capa(Capa.Prefetch)) {
ifvisible.idle(this.prefetchNextTick.bind(this));
}
}

View file

@ -12,11 +12,10 @@ import {
ClientSideKeyName,
FolderType,
Focused,
Layout,
MessageSetAction
} from 'Common/EnumsUser';
import { $htmlCL, leftPanelDisabled, keyScopeReal, moveAction, Settings } from 'Common/Globals';
import { $htmlCL, leftPanelDisabled, keyScopeReal, moveAction, Settings, isMobile } from 'Common/Globals';
import { inFocus } from 'Common/Utils';
import { mailToHelper } from 'Common/UtilsUser';
@ -86,8 +85,6 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
this.allowMessageActions = !!Settings.capa(Capa.MessageActions);
this.allowMessageListActions = !!Settings.capa(Capa.MessageListActions);
this.mobile = !!Settings.app('mobile');
this.attachmentsActions = AppStore.attachmentsActions;
this.message = MessageStore.message;
@ -287,14 +284,14 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
@command((self) => !self.messageListAndMessageViewLoading())
goUpCommand() {
dispatchEvent(new CustomEvent('mailbox.message-list.selector.go-up',
{detail:Layout.NoPreview === this.layout() ? !!this.message() : true}
{detail:SettingsStore.usePreviewPane() || !!this.message()}
));
}
@command((self) => !self.messageListAndMessageViewLoading())
goDownCommand() {
dispatchEvent(new CustomEvent('mailbox.message-list.selector.go-down',
{detail:Layout.NoPreview === this.layout() ? !!this.message() : true}
{detail:SettingsStore.usePreviewPane() || !!this.message()}
));
}
@ -408,7 +405,7 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
this.oHeaderDom = dom.querySelector('.messageItemHeader');
if (this.oHeaderDom) {
if (!this.resizeObserver) {
this.resizeObserver = new ResizeObserver(this.checkHeaderHeight.throttle(50).bind(this));
this.resizeObserver = new ResizeObserver(this.checkHeaderHeight.debounce(50).bind(this));
}
this.resizeObserver.observe(this.oHeaderDom);
} else if (this.resizeObserver) {
@ -417,7 +414,7 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
const eqs = (ev, s) => ev.target.closestWithin(s, dom);
dom.addEventListener('click', event => {
this.mobile && leftPanelDisabled(true);
isMobile() && leftPanelDisabled(true);
let el = eqs(event, 'a');
if (el) {
@ -506,7 +503,7 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
*/
escShortcuts() {
if (this.viewModelVisible && this.message()) {
const preview = Layout.NoPreview !== this.layout();
const preview = SettingsStore.usePreviewPane();
if (this.fullScreenMode()) {
this.fullScreenMode(false);
@ -616,7 +613,7 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
// change focused state
shortcuts.add('arrowleft', '', KeyState.MessageView, () => {
if (!this.fullScreenMode() && this.message() && Layout.NoPreview !== this.layout()) {
if (!this.fullScreenMode() && this.message() && SettingsStore.usePreviewPane()) {
if (this.oMessageScrollerDom && 0 < this.oMessageScrollerDom.scrollLeft) {
return true;
}
@ -626,7 +623,7 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
});
// shortcuts.add('tab', 'shift', KeyState.MessageView, (event, handler) => {
shortcuts.add('tab', '', KeyState.MessageView, () => {
if (!this.fullScreenMode() && this.message() && Layout.NoPreview !== this.layout()) {
if (!this.fullScreenMode() && this.message() && SettingsStore.usePreviewPane()) {
AppStore.focusedState(Focused.MessageList);
}
return false;

View file

@ -1,5 +1,5 @@
import { KeyState } from 'Common/Enums';
import { leftPanelDisabled } from 'Common/Globals';
import { leftPanelDisabled, isMobile } from 'Common/Globals';
import { settings, mailbox } from 'Common/Links';
import { getFolderInboxName } from 'Common/Cache';
@ -15,13 +15,11 @@ export class MenuSettingsUserView extends AbstractViewLeft {
this.leftPanelDisabled = leftPanelDisabled;
this.mobile = rl.settings.app('mobile');
this.menu = screen.menu;
}
onBuild(dom) {
if (this.mobile) {
if (isMobile()) {
dom.addEventListener('click', event =>
event.target.closestWithin('.b-settings-menu .e-item.selectable', dom) && leftPanelDisabled(true)
);

View file

@ -1,6 +1,6 @@
import { mailbox } from 'Common/Links';
import { getFolderInboxName } from 'Common/Cache';
import { leftPanelDisabled } from 'Common/Globals';
import { leftPanelDisabled, isMobile } from 'Common/Globals';
import MessageStore from 'Stores/User/Message';
@ -10,8 +10,6 @@ export class PaneSettingsUserView extends AbstractViewRight {
constructor() {
super('User/Settings/Pane', 'SettingsPane');
this.mobile = rl.settings.app('mobile');
this.leftPanelDisabled = leftPanelDisabled;
}
@ -34,7 +32,7 @@ export class PaneSettingsUserView extends AbstractViewRight {
}
onBuild(dom) {
this.mobile && dom.addEventListener('click', () => leftPanelDisabled(true));
isMobile() && dom.addEventListener('click', () => leftPanelDisabled(true));
}
backToMailBoxClick() {

View file

@ -129,7 +129,7 @@ win.rl = {
if (RL_APP_DATA.Title) {
title += (title ? ' - ' : '') + RL_APP_DATA.Title;
}
doc.title = null == title ? '' : '' + title;
doc.title = title;
},
initData: appData => {
@ -172,15 +172,7 @@ setInterval(setTimestamp, 60000); // 1m
[eId('app-css'),eId('app-theme-link')].forEach(css => css.href = css.dataset.href);
loadScript('./?/'
+ (options.admin ? 'Admin' : '')
+ 'AppData@'
+ (options.mobile ? 'mobile' : 'no-mobile')
+ (options.mobileDevice ? '-1' : '-0')
+ '/'
+ (rl.hash.get() || '0')
+ '/'
+ Math.random().toString().substr(2)
+ '/').then(() => {});
loadScript(`./?/${options.admin ? 'Admin' : ''}AppData/${rl.hash.get() || '0'}/${Math.random().toString().substr(2)}/`)
.then(() => {});
})(this);

View file

@ -660,7 +660,7 @@ class Actions
{
if (null === $this->oAddressBookProvider) {
$oDriver = null;
if ($this->GetCapa(false, false, Enumerations\Capa::CONTACTS, $oAccount)) {
if ($this->GetCapa(false, Enumerations\Capa::CONTACTS, $oAccount)) {
if ($this->Config()->Get('contacts', 'enable', false) || $bForceEnable) {
$oDriver = $this->fabrica('address-book', $oAccount);
}
@ -983,12 +983,12 @@ class Actions
return $this->GetAccountFromCustomToken($this->getLocalAuthToken(), $bThrowExceptionOnFalse, true, true);
}
public function AppDataSystem(bool $bAdmin = false, bool $bMobile = false, bool $bMobileDevice = false): array
public function AppDataSystem(bool $bAdmin = false): array
{
$oConfig = $this->Config();
$aAttachmentsActions = array();
if ($this->GetCapa(false, $bMobile, Enumerations\Capa::ATTACHMENTS_ACTIONS)) {
if ($this->GetCapa(false, Enumerations\Capa::ATTACHMENTS_ACTIONS)) {
if (\class_exists('PharData') || \class_exists('ZipArchive')) {
$aAttachmentsActions[] = 'zip';
}
@ -997,8 +997,6 @@ class Actions
return \array_merge(array(
'version' => APP_VERSION,
'admin' => $bAdmin,
'mobile' => $bMobile,
'mobileDevice' => $bMobileDevice,
'webPath' => Utils::WebPath(),
'webVersionPath' => Utils::WebVersionPath(),
'token' => $oConfig->Get('security', 'csrf_protection', false) ? Utils::GetCsrfToken() : '',
@ -1027,7 +1025,7 @@ class Actions
) : array());
}
public function AppData(bool $bAdmin, bool $bMobile = false, bool $bMobileDevice = false, string $sAuthAccountHash = ''): array
public function AppData(bool $bAdmin, string $sAuthAccountHash = ''): array
{
if (0 < \strlen($sAuthAccountHash) && \preg_match('/[^_\-\.a-zA-Z0-9]/', $sAuthAccountHash)) {
$sAuthAccountHash = '';
@ -1071,7 +1069,7 @@ class Actions
'Admin' => array(),
'Capa' => array(),
'Plugins' => array(),
'System' => $this->AppDataSystem($bAdmin, $bMobile, $bMobileDevice),
'System' => $this->AppDataSystem($bAdmin),
'NewMoveToFolder' => (bool) $oConfig->Get('interface', 'new_move_to_folder_button', true),
'AllowLanguagesOnSettings' => (bool) $oConfig->Get('webmail', 'allow_languages_on_settings', true),
@ -1165,11 +1163,11 @@ class Actions
}
}
$aResult['Capa'] = $this->Capa(false, $bMobile, $oAccount);
$aResult['Capa'] = $this->Capa(false, $oAccount);
if ($aResult['Auth'] && !$aResult['RequireTwoFactor']) {
if ($this->GetCapa(false, $bMobile, Enumerations\Capa::TWO_FACTOR, $oAccount) &&
$this->GetCapa(false, $bMobile, Enumerations\Capa::TWO_FACTOR_FORCE, $oAccount) &&
if ($this->GetCapa(false, Enumerations\Capa::TWO_FACTOR, $oAccount) &&
$this->GetCapa(false, Enumerations\Capa::TWO_FACTOR_FORCE, $oAccount) &&
$this->TwoFactorAuthProvider()->IsActive()) {
$aData = $this->getTwoFactorInfo($oAccount, true);
@ -1207,7 +1205,7 @@ class Actions
);
}
$aResult['Capa'] = $this->Capa(true, $bMobile);
$aResult['Capa'] = $this->Capa(true);
}
$aResult['ProjectHash'] = \md5($aResult['AccountHash'] . APP_VERSION . $this->Plugins()->Hash());
@ -1222,7 +1220,7 @@ class Actions
$oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);
if ($oSettingsLocal instanceof Settings) {
// if ($this->GetCapa(false, $bMobile, Enumerations\Capa::FOLDERS, $oAccount))
// if ($this->GetCapa(false, Enumerations\Capa::FOLDERS, $oAccount))
$aResult['SentFolder'] = (string)$oSettingsLocal->GetConf('SentFolder', '');
$aResult['DraftFolder'] = (string)$oSettingsLocal->GetConf('DraftFolder', '');
@ -1232,7 +1230,7 @@ class Actions
$aResult['NullFolder'] = (string)$oSettingsLocal->GetConf('NullFolder', '');
}
if ($this->GetCapa(false, $bMobile, Enumerations\Capa::SETTINGS, $oAccount)) {
if ($this->GetCapa(false, Enumerations\Capa::SETTINGS, $oAccount)) {
if ($oSettings instanceof Settings) {
if ($oConfig->Get('webmail', 'allow_languages_on_settings', true)) {
$sLanguage = (string)$oSettings->GetConf('Language', $sLanguage);
@ -1249,11 +1247,11 @@ class Actions
$aResult['AutoLogout'] = (int)$oSettings->GetConf('AutoLogout', $aResult['AutoLogout']);
$aResult['Layout'] = (int)$oSettings->GetConf('Layout', $aResult['Layout']);
if (!$this->GetCapa(false, $bMobile, Enumerations\Capa::AUTOLOGOUT, $oAccount)) {
if (!$this->GetCapa(false, Enumerations\Capa::AUTOLOGOUT, $oAccount)) {
$aResult['AutoLogout'] = 0;
}
if ($this->GetCapa(false, $bMobile, Enumerations\Capa::USER_BACKGROUND, $oAccount)) {
if ($this->GetCapa(false, Enumerations\Capa::USER_BACKGROUND, $oAccount)) {
$aResult['UserBackgroundName'] = (string)$oSettings->GetConf('UserBackgroundName', $aResult['UserBackgroundName']);
$aResult['UserBackgroundHash'] = (string)$oSettings->GetConf('UserBackgroundHash', $aResult['UserBackgroundHash']);
}
@ -1265,7 +1263,7 @@ class Actions
$aResult['UseThreads'] = (bool)$oSettingsLocal->GetConf('UseThreads', $aResult['UseThreads']);
$aResult['ReplySameFolder'] = (bool)$oSettingsLocal->GetConf('ReplySameFolder', $aResult['ReplySameFolder']);
if ($this->GetCapa(false, $bMobile, Enumerations\Capa::THEMES, $oAccount)) {
if ($this->GetCapa(false, Enumerations\Capa::THEMES, $oAccount)) {
$sTheme = (string)$oSettingsLocal->GetConf('Theme', $sTheme);
}
}
@ -1327,16 +1325,6 @@ class Actions
$aResult['MailToEmail'] = \MailSo\Base\Utils::IdnToUtf8($aResult['MailToEmail']);
$aResult['DevEmail'] = \MailSo\Base\Utils::IdnToUtf8($aResult['DevEmail']);
// Mobile override
if ($bMobile) {
$aResult['Layout'] = Enumerations\Layout::NO_PREVIEW;
$aResult['UseCheckboxesInList'] = true;
$aResult['UserBackgroundName'] = '';
$aResult['UserBackgroundHash'] = '';
}
$this->Plugins()->InitAppData($bAdmin, $aResult, $oAccount);
return $aResult;
@ -1611,7 +1599,7 @@ class Actions
public function GetAccounts(Model\Account $oAccount): array
{
if ($this->GetCapa(false, false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
if ($this->GetCapa(false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
$sAccounts = $this->StorageProvider()->Get($oAccount,
Providers\Storage\Enumerations\StorageType::CONFIG,
'accounts'
@ -1866,7 +1854,7 @@ class Actions
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Enumerations\Capa::USER_BACKGROUND, $oAccount)) {
if (!$this->GetCapa(false, Enumerations\Capa::USER_BACKGROUND, $oAccount)) {
return $this->FalseResponse(__FUNCTION__);
}
@ -2041,7 +2029,7 @@ class Actions
return $this->DefaultResponse(__FUNCTION__, true);
}
public function Capa(bool $bAdmin, bool $bMobile = false, ?Model\Account $oAccount = null): array
public function Capa(bool $bAdmin, ?Model\Account $oAccount = null): array
{
$oConfig = $this->Config();
@ -2078,7 +2066,7 @@ class Actions
$aResult[] = Enumerations\Capa::IDENTITIES;
}
if ($oConfig->Get('capa', 'x-templates', true) && !$bMobile) {
if ($oConfig->Get('capa', 'x-templates', true)) {
$aResult[] = Enumerations\Capa::TEMPLATES;
}
@ -2086,11 +2074,11 @@ class Actions
$aResult[] = Enumerations\Capa::THEMES;
}
if ($oConfig->Get('webmail', 'allow_user_background', false) && !$bMobile) {
if ($oConfig->Get('webmail', 'allow_user_background', false)) {
$aResult[] = Enumerations\Capa::USER_BACKGROUND;
}
if ($oConfig->Get('security', 'openpgp', false) && !$bMobile) {
if ($oConfig->Get('security', 'openpgp', false)) {
$aResult[] = Enumerations\Capa::OPEN_PGP;
}
@ -2112,7 +2100,7 @@ class Actions
}
}
if ($oConfig->Get('capa', 'help', true) && !$bMobile) {
if ($oConfig->Get('capa', 'help', true)) {
$aResult[] = Enumerations\Capa::HELP;
}
@ -2135,7 +2123,7 @@ class Actions
if ($oConfig->Get('capa', 'search', true)) {
$aResult[] = Enumerations\Capa::SEARCH;
if ($oConfig->Get('capa', 'search_adv', true) && !$bMobile) {
if ($oConfig->Get('capa', 'search_adv', true)) {
$aResult[] = Enumerations\Capa::SEARCH_ADV;
}
}
@ -2144,7 +2132,7 @@ class Actions
$aResult[] = Enumerations\Capa::ATTACHMENT_THUMBNAILS;
}
if ($oConfig->Get('labs', 'allow_prefetch', false) && !$bMobile) {
if ($oConfig->Get('labs', 'allow_prefetch', false)) {
$aResult[] = Enumerations\Capa::PREFETCH;
}
@ -2153,9 +2141,9 @@ class Actions
return $aResult;
}
public function GetCapa(bool $bAdmin, bool $bMobile, string $sName, ?Model\Account $oAccount = null): bool
public function GetCapa(bool $bAdmin, string $sName, ?Model\Account $oAccount = null): bool
{
return \in_array($sName, $this->Capa($bAdmin, $bMobile, $oAccount));
return \in_array($sName, $this->Capa($bAdmin, $oAccount));
}
public function etag(string $sKey): string

View file

@ -20,7 +20,7 @@ trait Accounts
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
if (!$this->GetCapa(false, Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
return $this->FalseResponse(__FUNCTION__);
}
@ -58,7 +58,7 @@ trait Accounts
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
if (!$this->GetCapa(false, Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
return $this->FalseResponse(__FUNCTION__);
}
@ -109,7 +109,7 @@ trait Accounts
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::IDENTITIES, $oAccount)) {
if (!$this->GetCapa(false, Capa::IDENTITIES, $oAccount)) {
return $this->FalseResponse(__FUNCTION__);
}
@ -154,7 +154,7 @@ trait Accounts
$mAccounts = false;
if ($this->GetCapa(false, false, Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
if ($this->GetCapa(false, Capa::ADDITIONAL_ACCOUNTS, $oAccount)) {
$mAccounts = $this->GetAccounts($oAccount);
$mAccounts = \array_keys($mAccounts);
@ -176,7 +176,7 @@ trait Accounts
public function GetIdentities(Account $account): array
{
// A custom name for a single identity is also stored in this system
$allowMultipleIdentities = $this->GetCapa(false, false, Capa::IDENTITIES, $account);
$allowMultipleIdentities = $this->GetCapa(false, Capa::IDENTITIES, $account);
// Get all identities
$identities = $this->IdentitiesProvider()->GetIdentities($account, $allowMultipleIdentities);

View file

@ -18,7 +18,7 @@ trait Filters
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::FILTERS, $oAccount))
if (!$this->GetCapa(false, Capa::FILTERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -44,7 +44,7 @@ trait Filters
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::FILTERS, $oAccount)) {
if (!$this->GetCapa(false, Capa::FILTERS, $oAccount)) {
return $this->FalseResponse(__FUNCTION__);
}
@ -79,7 +79,7 @@ trait Filters
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::FILTERS, $oAccount)) {
if (!$this->GetCapa(false, Capa::FILTERS, $oAccount)) {
return $this->FalseResponse(__FUNCTION__);
}
@ -95,7 +95,7 @@ trait Filters
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::FILTERS, $oAccount)) {
if (!$this->GetCapa(false, Capa::FILTERS, $oAccount)) {
return $this->FalseResponse(__FUNCTION__);
}

View file

@ -17,7 +17,7 @@ trait Folders
$oFolderCollection = null;
$this->Plugins()->RunHook('filter.folders-before', array($oAccount, $oFolderCollection));
$bUseFolders = $this->GetCapa(false, false, Capa::FOLDERS, $oAccount);
$bUseFolders = $this->GetCapa(false, Capa::FOLDERS, $oAccount);
if (null === $oFolderCollection)
{
@ -157,7 +157,7 @@ trait Folders
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
if (!$this->GetCapa(false, Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -182,7 +182,7 @@ trait Folders
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
if (!$this->GetCapa(false, Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -213,7 +213,7 @@ trait Folders
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
if (!$this->GetCapa(false, Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -263,7 +263,7 @@ trait Folders
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
if (!$this->GetCapa(false, Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -291,7 +291,7 @@ trait Folders
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
if (!$this->GetCapa(false, Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}

View file

@ -99,7 +99,7 @@ trait Messages
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, false, Capa::COMPOSER, $oAccount))
if (!$this->GetCapa(false, Capa::COMPOSER, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -166,7 +166,7 @@ trait Messages
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, false, Capa::COMPOSER, $oAccount))
if (!$this->GetCapa(false, Capa::COMPOSER, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -349,7 +349,7 @@ trait Messages
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, false, Capa::COMPOSER, $oAccount))
if (!$this->GetCapa(false, Capa::COMPOSER, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}

View file

@ -232,8 +232,6 @@ trait Response
$mResult[$prop] = $this->responseObject($mResult[$prop], $sParent, $aParameters);
}
$mResult['SubjectParts'] = $this->explodeSubject($mResult['Subject']);
$sSubject = $mResult['Subject'];
$mResult['Hash'] = \md5($mResult['Folder'].$mResult['Uid']);
$mResult['RequestHash'] = Utils::EncodeKeyValuesQ(array(
@ -252,7 +250,7 @@ trait Response
$mResult['IsForwarded'] = \strlen($sForwardedFlag) && \in_array(\strtolower($sForwardedFlag), $aFlags);
$mResult['IsReadReceipt'] = \strlen($sReadReceiptFlag) && \in_array(\strtolower($sReadReceiptFlag), $aFlags);
if (!$this->GetCapa(false, false, Capa::COMPOSER, $oAccount))
if (!$this->GetCapa(false, Capa::COMPOSER, $oAccount))
{
$mResult['IsReadReceipt'] = true;
}
@ -392,7 +390,7 @@ trait Response
|| ($mFoundedContentLocationUrls && \in_array(\trim($mResponse->ContentLocation()), $mFoundedContentLocationUrls));
$mResult['Framed'] = $this->isFileHasFramedPreview($mResult['FileName']);
$mResult['IsThumbnail'] = $this->GetCapa(false, false, Capa::ATTACHMENT_THUMBNAILS) && $this->isFileHasThumbnail($mResult['FileName']);
$mResult['IsThumbnail'] = $this->GetCapa(false, Capa::ATTACHMENT_THUMBNAILS) && $this->isFileHasThumbnail($mResult['FileName']);
$mResult['Download'] = Utils::EncodeKeyValuesQ(array(
'V' => APP_VERSION,
@ -466,48 +464,4 @@ trait Response
return $mResponse;
}
private function explodeSubject(string $sSubject) : array
{
$aResult = array('', '');
if (0 < \strlen($sSubject))
{
$bDrop = false;
$aPrefix = array();
$aSuffix = array();
$aParts = \explode(':', $sSubject);
foreach ($aParts as $sPart)
{
if (!$bDrop &&
(\preg_match('/^(RE|FWD)$/i', \trim($sPart)) || \preg_match('/^(RE|FWD)[\[\(][\d]+[\]\)]$/i', \trim($sPart))))
{
$aPrefix[] = $sPart;
}
else
{
$aSuffix[] = $sPart;
$bDrop = true;
}
}
if (0 < \count($aPrefix))
{
$aResult[0] = \rtrim(\trim(\implode(':', $aPrefix)), ':').': ';
}
if (0 < \count($aSuffix))
{
$aResult[1] = \trim(\implode(':', $aSuffix));
}
if (0 === \strlen($aResult[1]))
{
$aResult = array('', $sSubject);
}
}
return $aResult;
}
}

View file

@ -18,7 +18,7 @@ trait Templates
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::TEMPLATES, $oAccount))
if (!$this->GetCapa(false, Capa::TEMPLATES, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -58,7 +58,7 @@ trait Templates
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::TEMPLATES, $oAccount))
if (!$this->GetCapa(false, Capa::TEMPLATES, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -89,7 +89,7 @@ trait Templates
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::TEMPLATES, $oAccount))
if (!$this->GetCapa(false, Capa::TEMPLATES, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -123,7 +123,7 @@ trait Templates
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::TEMPLATES, $oAccount))
if (!$this->GetCapa(false, Capa::TEMPLATES, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}

View file

@ -16,7 +16,7 @@ trait TwoFactor
$oAccount = $this->getAccountFromToken();
if (!$this->TwoFactorAuthProvider()->IsActive() ||
!$this->GetCapa(false, false, Capa::TWO_FACTOR, $oAccount))
!$this->GetCapa(false, Capa::TWO_FACTOR, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -30,7 +30,7 @@ trait TwoFactor
$oAccount = $this->getAccountFromToken();
if (!$this->TwoFactorAuthProvider()->IsActive() ||
!$this->GetCapa(false, false, Capa::TWO_FACTOR, $oAccount))
!$this->GetCapa(false, Capa::TWO_FACTOR, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -67,7 +67,7 @@ trait TwoFactor
$oAccount = $this->getAccountFromToken();
if (!$this->TwoFactorAuthProvider()->IsActive() ||
!$this->GetCapa(false, false, Capa::TWO_FACTOR, $oAccount))
!$this->GetCapa(false, Capa::TWO_FACTOR, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -83,7 +83,7 @@ trait TwoFactor
$oAccount = $this->getAccountFromToken();
if (!$this->TwoFactorAuthProvider()->IsActive() ||
!$this->GetCapa(false, false, Capa::TWO_FACTOR, $oAccount))
!$this->GetCapa(false, Capa::TWO_FACTOR, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -114,7 +114,7 @@ trait TwoFactor
$oAccount = $this->getAccountFromToken();
if (!$this->TwoFactorAuthProvider()->IsActive() ||
!$this->GetCapa(false, false, Capa::TWO_FACTOR, $oAccount))
!$this->GetCapa(false, Capa::TWO_FACTOR, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -140,7 +140,7 @@ trait TwoFactor
$oAccount = $this->getAccountFromToken();
if (!$this->TwoFactorAuthProvider()->IsActive() ||
!$this->GetCapa(false, false, Capa::TWO_FACTOR, $oAccount))
!$this->GetCapa(false, Capa::TWO_FACTOR, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}

View file

@ -90,7 +90,7 @@ trait User
*/
public function DoAttachmentsActions() : array
{
if (!$this->GetCapa(false, false, Capa::ATTACHMENTS_ACTIONS))
if (!$this->GetCapa(false, Capa::ATTACHMENTS_ACTIONS))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -311,7 +311,7 @@ trait User
public function DoSettingsUpdate() : array
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::SETTINGS, $oAccount))
if (!$this->GetCapa(false, Capa::SETTINGS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -333,7 +333,7 @@ trait User
$oSettings->SetConf('Language', $this->ValidateLanguage($oConfig->Get('webmail', 'language', 'en')));
}
if ($this->GetCapa(false, false, Capa::THEMES, $oAccount))
if ($this->GetCapa(false, Capa::THEMES, $oAccount))
{
$this->setSettingsFromParams($oSettingsLocal, 'Theme', 'string', function ($sTheme) use ($self) {
return $self->ValidateTheme($sTheme);
@ -377,7 +377,7 @@ trait User
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, false, Capa::QUOTA, $oAccount))
if (!$this->GetCapa(false, Capa::QUOTA, $oAccount))
{
return $this->DefaultResponse(__FUNCTION__, array(0, 0, 0, 0));
}
@ -510,7 +510,7 @@ trait User
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, false, Capa::USER_BACKGROUND, $oAccount))
if (!$this->GetCapa(false, Capa::USER_BACKGROUND, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}

View file

@ -308,9 +308,6 @@ Enables caching in the system'),
),
'labs' => array(
'allow_mobile_version' => array(true,
'Experimental settings. Handle with care.
'),
'ignore_folders_subscription' => array(false),
'update_channel' => array('stable'),
'allow_prefetch' => array(true),

View file

@ -142,27 +142,6 @@ class Service
if ($bIndex)
{
$bMobile = false;
$bMobileDevice = false;
if ($this->oActions->Config()->Get('labs', 'allow_mobile_version', false))
{
$bUseMobileVersionForTablets = $this->oActions->Config()->Get('labs', 'use_mobile_version_for_tablets', false);
$bMobileDevice = UserAgent::isMobile() &&
($bUseMobileVersionForTablets ? true : !UserAgent::isTablet());
$sMobileType = (string) Utils::GetCookie(Actions::RL_MOBILE_TYPE, '');
switch ($sMobileType) {
default:
$bMobile = $bMobileDevice;
break;
case 'mobile':
$bMobile = true;
break;
case 'desktop':
$bMobile = false;
break;
}
}
header('Content-Type: text/html; charset=utf-8');
$this->oHttp->ServerNoCache();
@ -176,7 +155,7 @@ class Service
return $this;
}
$aTemplateParameters = $this->indexTemplateParameters($bAdmin, $bMobile, $bMobileDevice);
$aTemplateParameters = $this->indexTemplateParameters($bAdmin);
$sCacheFileName = '';
if ($this->oActions->Config()->Get('labs', 'cache_system_data', true) && !empty($aTemplateParameters['{{BaseHash}}']))
@ -207,12 +186,6 @@ class Service
$sResult .= '][cached:'.($bCached ? 'true' : 'false');
// $sResult .= '][hash:'.$aTemplateParameters['{{BaseHash}}'];
// $sResult .= '][session:'.\md5(Utils::GetShortToken());
if ($bMobile)
{
$sResult .= '][mobile:true';
}
$sResult .= ']-->';
}
else if (!headers_sent())
@ -233,12 +206,25 @@ class Service
return $this->oActions->StaticPath($sPath);
}
private function indexTemplateParameters(bool $bAdmin = false, bool $bMobile = false, bool $bMobileDevice = false) : array
private function indexTemplateParameters(bool $bAdmin = false) : array
{
$sLanguage = 'en';
$sTheme = 'Default';
switch (Utils::GetCookie(Actions::RL_MOBILE_TYPE, '')) {
case 'mobile':
$bMobile = true;
break;
case 'desktop':
$bMobile = false;
break;
default:
$bMobile = UserAgent::isMobile() && (
$this->oActions->Config()->Get('labs', 'use_mobile_version_for_tablets', false)
|| !UserAgent::isTablet());
break;
}
list($sLanguage, $sTheme) = $this->oActions->GetLanguageAndTheme($bAdmin, $bMobile);
list($sLanguage, $sTheme) = $this->oActions->GetLanguageAndTheme($bAdmin);
$oConfig = $this->oActions->Config();
@ -262,19 +248,17 @@ class Service
'{{BaseAppPolyfillsScriptLink}}' => '',
'{{BaseAppBootScriptLink}}' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').'boot'.($bAppJsDebug ? '' : '.min').'.js'),
'{{BaseAppBootScript}}' => \file_get_contents(APP_VERSION_ROOT_PATH.'static/js/min/boot.min.js'),
'{{BaseViewport}}' => $bMobile ? 'width=device-width,initial-scale=1,user-scalable=no' : 'width=950,maximum-scale=2',
'{{BaseContentSecurityPolicy}}' => '',
'{{BaseDir}}' => false && \in_array($sLanguage, array('ar', 'he', 'ur')) ? 'rtl' : 'ltr',
'{{BaseAppManifestLink}}' => $this->staticPath('manifest.json'),
'{{BaseAppBootCss}}' => \file_get_contents(APP_VERSION_ROOT_PATH.'static/css/boot.min.css'),
'{{BaseCssClass}}' => ($bMobileDevice ? 'mobile' : 'no-mobile') . ($bMobile ? ' rl-mobile' : ''),
'{{BaseCssClass}}' => $bMobile ? ' rl-mobile' : '',
'{{LoadingDescriptionEsc}}' => \htmlspecialchars($LoadingDescription, ENT_QUOTES|ENT_IGNORE, 'UTF-8'),
'{{RainloopBootData}}' => \json_encode(array(
'admin' => $bAdmin,
'language' => $sLanguage,
'theme' => $sTheme,
'mobile' => $bMobile,
'mobileDevice' => $bMobileDevice
'mobile' => $bMobile
))
);

View file

@ -661,14 +661,14 @@ class ServiceActions
return $bJson ? \MailSo\Base\Utils::Php2js(array($sTheme, $sResult), $this->Logger()) : $sResult;
}
public function ServiceAppData(string $sAdd = '') : string
public function ServiceAppData() : string
{
return $this->localAppData(false, $sAdd);
return $this->localAppData(false);
}
public function ServiceAdminAppData(string $sAdd = '') : string
public function ServiceAdminAppData() : string
{
return $this->localAppData(true, $sAdd);
return $this->localAppData(true);
}
public function ServiceMobileVersion() : string
@ -897,7 +897,7 @@ class ServiceActions
$oAccount = $this->oActions->GetAccount();
if ($oAccount && $this->oActions->GetCapa(false, false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount))
if ($oAccount && $this->oActions->GetCapa(false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount))
{
$oAccountToLogin = null;
$sEmail = empty($this->aPaths[2]) ? '' : \urldecode(\trim($this->aPaths[2]));
@ -948,7 +948,7 @@ class ServiceActions
return $this->ErrorTemplates($sTitle, \nl2br($sDesc));
}
private function localAppData(bool $bAdmin = false, string $sAdd = '') : string
private function localAppData(bool $bAdmin = false) : string
{
\header('Content-Type: application/javascript; charset=utf-8');
$this->oHttp->ServerNoCache();
@ -987,9 +987,7 @@ class ServiceActions
}
$sResult = 'rl.initData('
.\json_encode($this->oActions->AppData($bAdmin,
0 === \strpos($sAdd, 'mobile'), '1' === \substr($sAdd, -1),
$sAuthAccountHash))
.\json_encode($this->oActions->AppData($bAdmin, $sAuthAccountHash))
.');';
$this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'APPDATA');

View file

@ -6,7 +6,7 @@
<meta http-equiv="refresh" content="0; URL=./?/NoScript" />
</noscript>
<meta charset="utf-8" />
<meta name="viewport" content="{{BaseViewport}}">
<meta name="viewport" content="width=device-width">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="google" content="notranslate" />
<meta name="robots" content="noindex,nofollow,noodp" />

View file

@ -52,9 +52,7 @@
autocorrect="off" autocapitalize="off" spellcheck="false" style="padding-right: 35px;"
data-bind="textInput: additionalCode, disable: submitRequest"
data-i18n="[placeholder]LOGIN/LABEL_VERIFICATION_CODE" />
<span class="add-on">
<i class="fontastic">🔑</i>
</span>
<span class="add-on fontastic">🔑</span>
</div>
</div>
<div class="controls plugin-mark-Login-BottomControlGroup"
@ -109,19 +107,15 @@
</form>
</div>
<div class="e-mobile-switcher">
<span data-bind="visible: !mobile">
<span class="hide-mobile">
<i class="fontastic">📱</i>
&nbsp;
<a href="./?/MobileVersion/" tabindex="-1">
<span data-i18n="MOBILE/BUTTON_MOBILE_VERSION"></span>
</a>
<a href="./?/MobileVersion/" tabindex="-1" data-i18n="MOBILE/BUTTON_MOBILE_VERSION"></a>
</span>
<span data-bind="visible: mobile">
<span class="show-mobile">
<i class="fontastic">💻</i>
&nbsp;
<a href="./?/DesktopVersion/" tabindex="-1">
<span data-i18n="MOBILE/BUTTON_DESKTOP_VERSION"></span>
</a>
<a href="./?/DesktopVersion/" tabindex="-1" data-i18n="MOBILE/BUTTON_DESKTOP_VERSION"></a>
</span>
</div>
</div>

View file

@ -1,5 +1,5 @@
<div class="b-folders g-ui-user-select-none" data-bind="css: {'focused': folderListFocused, 'single-root-inbox': foldersListWithSingleInboxRootFolder, 'inbox-is-starred': isInboxStarred}">
<div class="b-toolbar btn-toolbar hide-on-mobile">
<div class="b-toolbar btn-toolbar hide-mobile">
<a class="btn buttonCompose" data-bind="visible: allowComposer, click: composeClick, tooltip: 'FOLDER_LIST/BUTTON_NEW_MESSAGE', css: {'btn-warning': composeInEdit, 'btn-success': !composeInEdit()}">
<i class="icon-paper-plane"></i>
<span class="buttonComposeText" data-i18n="FOLDER_LIST/BUTTON_NEW_MESSAGE"></span>
@ -17,7 +17,7 @@
</div>
</div>
<div class="b-content show-on-panel-disabled" data-bind="click: function () { leftPanelDisabled(false); }"></div>
<div class="b-footer btn-toolbar hide-on-mobile" data-bind="visible: allowFolders">
<div class="b-footer btn-toolbar hide-mobile" data-bind="visible: allowFolders">
<div class="btn-group">
<a class="btn buttonResize" data-bind="click: function () { leftPanelDisabled(!leftPanelDisabled()); }">
<i data-bind="css: {'icon-resize-out': leftPanelDisabled(), 'icon-resize-in': !leftPanelDisabled()}"></i>
@ -27,9 +27,7 @@
<a class="btn" data-bind="click: createFolder">
<i data-bind="css: {'icon-folder-add': !foldersChanging(), 'icon-spinner': foldersChanging()}"></i>
</a>
<a class="btn" data-bind="click: configureFolders">
<i class="fontastic"></i>
</a>
<a class="btn fontastic" data-bind="click: configureFolders"></a>
</div>
</div>
</div>

View file

@ -3,24 +3,22 @@
data-bind="css: {'message-selected': isMessageSelected, 'message-focused': !messageListFocused(), 'hideMessageListCheckbox': !useCheckboxesInList() }">
<div class="toolbar">
<div class="btn-toolbar">
<!-- ko if: mobile -->
<!-- ko if: allowFolders -->
<a class="btn btn-thin-2" data-bind="click: showLeft, visible: leftPanelDisabled()">
<a class="btn btn-thin-2 show-mobile" data-bind="click: showLeft, visible: leftPanelDisabled()">
<i class="icon-right-middle"></i>
</a>
<a class="btn btn-thin-2" data-bind="click: hideLeft, visible: !leftPanelDisabled()">
<a class="btn btn-thin-2 show-mobile" data-bind="click: hideLeft, visible: !leftPanelDisabled()">
<i class="icon-left-middle"></i>
</a>
<!-- /ko -->
<a class="btn buttonCompose" data-bind="click: composeClick, tooltip: 'FOLDER_LIST/BUTTON_NEW_MESSAGE', css: {'btn-warning': composeInEdit, 'btn-success': !composeInEdit()}, visible: allowComposer && mobileCheckedStateHide()">
<a class="btn buttonCompose show-mobile" data-bind="click: composeClick, tooltip: 'FOLDER_LIST/BUTTON_NEW_MESSAGE', css: {'btn-warning': composeInEdit, 'btn-success': !composeInEdit()}, visible: allowComposer && mobileCheckedStateHide()">
<i class="icon-paper-plane"></i>
</a>
<!-- /ko -->
<a class="btn buttonReload" data-bind="command: reloadCommand, tooltip: 'MESSAGE_LIST/BUTTON_RELOAD', visible: allowReload && mobileCheckedStateHide()">
<i class="icon-spinner" data-bind="css: {'not-animated': !messageListCompleteLoadingThrottleForAnimation()}"></i>
</a>
<!-- ko if: !newMoveToFolder -->
<div class="btn-group dropdown colored-toggle hide-on-mobile" data-bind="visible: allowMessageListActions, registerBootstrapDropdown: true, openDropdownTrigger: moveDropdownTrigger">
<div class="btn-group dropdown colored-toggle hide-mobile" data-bind="visible: allowMessageListActions, registerBootstrapDropdown: true, openDropdownTrigger: moveDropdownTrigger">
<a id="move-dropdown-id" href="#" tabindex="-1" class="btn dropdown-toggle buttonMove" data-toggle="dropdown" data-bind="command: moveCommand, tooltip: 'GLOBAL/MOVE_TO'">
<i class="icon-copy visible-on-ctrl-btn"></i>
<i class="fontastic hidden-on-ctrl-btn">📁</i>
@ -157,7 +155,47 @@
<span data-i18n="MESSAGE_LIST/EMPTY_SEARCH_LIST"></span>
</div>
<div data-bind="dragmessages: getDragData">
<div class="messageListPlace" data-bind="template: { name: messageListItemTemplate(), foreach: messageList }"></div>
<div class="messageListPlace" data-bind="foreach: messageList">
<div class="messageListItem" data-bind="css: lineAsCss()">
<div class="checkboxMessage fontastic" data-bind="text: checked() ? '☑' : '☐'"></div>
<div class="flagParent">
<i class="flagOn fontastic"></i>
<i class="flagOnHalf fontastic"></i>
<i class="flagOff fontastic"></i>
<!-- ⚐⚑ -->
</div>
<div class="senderParent actionHandle">
<i class="replyFlag fontastic"></i>
<i class="forwardFlag fontastic"></i>
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
</div>
<div class="attachmentParent actionHandle">
<i data-bind="css: attachmentIconClass"></i>
</div>
<div class="subjectParent actionHandle">
<b class="importantMark">!</b>
<span class="emptySubjectText" data-bind="text: $root.emptySubjectValue"></span>
<span class="subject" data-bind="text: subject"></span>
</div>
<div class="threadsParent" data-bind="visible: 1 < threadsLen()">
<span class="threads-len">
<span class="threads-len-data">
<span data-bind="text: threadsLen"></span>
<i class="icon-right-mini"></i>
</span>
</span>
</div>
<time class="actionHandle" data-moment-format="SHORT" data-moment-format-title="FULL" data-bind="moment: dateTimeStampInUTC"></time>
</div>
</div>
</div>
<div id="messagesDragImage"><span class="text"></span>&nbsp;<i class="icon-mail icon-white"></i></div>
</div>

View file

@ -1,41 +0,0 @@
<div class="messageListItem" data-bind="css: lineAsCss()">
<div class="sidebarParent">
&nbsp;
</div>
<div class="delimiter"></div>
<div class="wrapper">
<div class="flagParent">
<i class="flagOn fontastic"></i>
<i class="flagOnHalf fontastic"></i>
<i class="flagOff fontastic"></i>
</div>
<div class="dateParent actionHandle">
<time class="date" data-moment-format="SHORT" data-moment-format-title="FULL" data-bind="moment: dateTimeStampInUTC"></time>
</div>
<div class="threadsParent" data-bind="visible: 1 < threadsLen()">
<span class="threads-len">
<span class="threads-len-data">
<span data-bind="text: threadsLen"></span>
<i class="icon-right-mini"></i>
</span>
</span>
</div>
<div class="checkboxMessage fontastic" data-bind="text: checked() ? '☑' : '☐'"></div>
<div class="senderParent actionHandle">
<span class="replyFlag"><i class="fontastic"></i>&nbsp;</span>
<span class="forwardFlag"><i class="fontastic"></i>&nbsp;</span>
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
&nbsp;
</div>
<div class="attachmentParent actionHandle">
<span class="attachment">
<i data-bind="css: attachmentIconClass"></i>
</span>
</div>
<div class="subjectParent actionHandle">
<b class="importantMark">!</b>
<span class="subject emptySubjectText" data-bind="text: $root.emptySubjectValue"></span>
<span class="subject-prefix" data-bind="text: subjectPrefix"></span><span class="subject-suffix" data-bind="text: subjectSuffix"></span>
</div>
</div>
</div>

View file

@ -1,42 +0,0 @@
<div class="messageListItem e-single-line" data-bind="css: lineAsCss()">
<div class="sidebarParent">
&nbsp;
</div>
<div class="delimiter"></div>
<div class="wrapper">
<div class="dateParent actionHandle">
<time class="date" data-moment-format="SHORT" data-moment-format-title="FULL" data-bind="moment: dateTimeStampInUTC"></time>
</div>
<div class="threadsParent" data-bind="visible: 1 < threadsLen()">
<span class="threads-len">
<span class="threads-len-data">
<span data-bind="text: threadsLen"></span>
<i class="icon-right-mini"></i>
</span>
</span>
</div>
<div class="checkboxMessage fontastic" data-bind="text: checked() ? '☑' : '☐'"></div>
<div class="flagParent">
<i class="flagOn fontastic"></i>
<i class="flagOnHalf fontastic"></i>
<i class="flagOff fontastic"></i>
</div>
<div class="senderParent actionHandle">
<span class="replyFlag"><i class="fontastic"></i>&nbsp;</span>
<span class="forwardFlag"><i class="fontastic"></i>&nbsp;</span>
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
&nbsp;
</div>
<div class="attachmentParent actionHandle">
<span class="attachment">
<i data-bind="css: attachmentIconClass"></i>
</span>
</div>
<div class="subjectParent actionHandle">
<b class="importantMark">!</b>
<span class="subject emptySubjectText" data-bind="text: $root.emptySubjectValue"></span>
<span class="subject-prefix" data-bind="text: subjectPrefix"></span><span class="subject-suffix" data-bind="text: subjectSuffix"></span>
</div>
<div class="clearfix"></div>
</div>
</div>

View file

@ -3,14 +3,10 @@
<div class="toolbar top-toolbar g-ui-user-select-none" data-bind="visible: !usePreviewPane()">
<div class="messageButtons btn-toolbar">
<div class="btn-group" data-bind="tooltip: 'GLOBAL/CLOSE'">
<a class="btn buttonClose" data-bind="command: closeMessageCommand">
<i class="fontastic"></i>
</a>
<a class="btn buttonClose fontastic" data-bind="command: closeMessageCommand"></a>
</div>
<div class="btn-group" data-bind="visible: isDraftFolder(), tooltip: 'MESSAGE/BUTTON_EDIT'">
<a class="btn btn-success buttonEdit" data-bind="command: messageEditCommand">
<i class="fontastic icon-white">🖉</i>
</a>
<a class="btn btn-success buttonEdit fontastic icon-white" data-bind="command: messageEditCommand">🖉</a>
</div>
<div class="btn-group">
<a class="btn button-archive" data-bind="visible: !isDraftFolder() && !isArchiveFolder() && !isArchiveDisabled(), command: archiveCommand, tooltip: 'GLOBAL/TO_ARCHIVE'">
@ -55,18 +51,12 @@
<div class="message-fixed-button-toolbar" data-bind="visible: message">
<div class="btn-group" style="margin-right: -11px;">
<a class="btn btn-thin-2 btn-transparent buttonReply"
data-bind="visible: 'reply' === lastReplyAction() && allowComposer, command: replyCommand, tooltip: 'MESSAGE/BUTTON_REPLY'">
<i class="fontastic"></i>
</a>
<a class="btn btn-thin-2 btn-transparent buttonReplyAll"
data-bind="visible: 'replyall' === lastReplyAction() && allowComposer, command: replyAllCommand, tooltip: 'MESSAGE/BUTTON_REPLY_ALL'">
<i class="fontastic"></i>
</a>
<a class="btn btn-thin-2 btn-transparent buttonForward"
data-bind="visible: 'forward' === lastReplyAction() && allowComposer, command: forwardCommand, tooltip: 'MESSAGE/BUTTON_FORWARD'">
<i class="fontastic"></i>
</a>
<a class="btn btn-thin-2 btn-transparent buttonReply fontastic"
data-bind="visible: 'reply' === lastReplyAction() && allowComposer, command: replyCommand, tooltip: 'MESSAGE/BUTTON_REPLY'">←</a>
<a class="btn btn-thin-2 btn-transparent buttonReplyAll fontastic"
data-bind="visible: 'replyall' === lastReplyAction() && allowComposer, command: replyAllCommand, tooltip: 'MESSAGE/BUTTON_REPLY_ALL'">↞</a>
<a class="btn btn-thin-2 btn-transparent buttonForward fontastic"
data-bind="visible: 'forward' === lastReplyAction() && allowComposer, command: forwardCommand, tooltip: 'MESSAGE/BUTTON_FORWARD'">→</a>
<div class="btn-group" data-bind="registerBootstrapDropdown: true, visible: allowComposer || allowMessageListActions || allowMessageActions" style="display: inline-block">
<a class="btn btn-thin-2 btn-transparent dropdown-toggle" id="more-view-dropdown-id" href="#" tabindex="-1" data-toggle="dropdown" style="margin-left: -4px; margin-right: 2px" data-bind="command: messageVisibilityCommand">
<span data-bind="visible: !allowComposer" class="fontastic"></span>
@ -167,10 +157,8 @@
</div>
</div>
<div class="btn-group hide-on-mobile" data-bind="visible: isDraftFolder(), tooltip: 'MESSAGE/BUTTON_EDIT'" style="margin-right: 5px">
<a class="btn btn-success buttonEdit" data-bind="command: messageEditCommand">
<i class="fontastic icon-white">🖉</i>
</a>
<div class="btn-group hide-mobile" data-bind="visible: isDraftFolder(), tooltip: 'MESSAGE/BUTTON_EDIT'" style="margin-right: 5px">
<a class="btn btn-success buttonEdit fontastic icon-white" data-bind="command: messageEditCommand">🖉</a>
</div>
</div>
@ -302,18 +290,14 @@
<i class="attachmentIconText attachmentMainIconText" data-bind="text: iconText()"></i>
</div>
<div class="iconBG" data-bind="attr: { 'style': linkThumbnailPreviewStyle() }"></div>
<div class="iconPreview">
<i class="attachmentIcon fontastic show-hover">👁</i>
</div>
<div class="iconPreview attachmentIcon fontastic show-hover">👁</div>
</a>
</div>
<div class="showPreplay">
<div class="iconMain">
<i class="attachmentIcon attachmentMainIcon" data-bind="css: iconClass()"></i>
</div>
<div class="iconPreview">
<i class="attachmentIcon fontastic show-hover"></i>
</div>
<div class="iconPreview attachmentIcon fontastic show-hover"></div>
</div>
</div>
<div class="attachmentNameParent">

View file

@ -2,11 +2,11 @@
<div class="modal-header b-header-toolbar g-ui-user-select-none">
<a class="btn btn-large button-send" data-bind="command: sendCommand, tooltipErrorTip: sendErrorDesc, css: {'btn-success': sendButtonSuccess, 'btn-danger': sendError, 'btn-warning': sendSuccessButSaveError }">
<i class="icon-white" data-bind="css: {'icon-paper-plane': !sending(), 'icon-spinner big': sending()}"></i>
<span class="i18n hide-on-mobile" data-i18n="COMPOSE/BUTTON_SEND"></span>
<span class="i18n hide-mobile" data-i18n="COMPOSE/BUTTON_SEND"></span>
</a>
<a class="btn button-save" data-bind="visible: allowFolders, command: saveCommand, tooltipErrorTip: savedErrorDesc, css: {'btn-danger': savedError }">
<i class="fontastic" data-bind="css: {'icon-spinner': saving(), 'icon-white': savedError()}">💾</i>
<span class="i18n hide-on-mobile" data-i18n="GLOBAL/SAVE"></span>
<span class="i18n hide-mobile" data-i18n="GLOBAL/SAVE"></span>
</a>
<a class="close" data-bind="click: tryToClosePopup, tooltip: 'GLOBAL/CANCEL'">×</a>
@ -15,7 +15,7 @@
<a class="btn btn-danger button-delete button-delete-transitions" data-bind="command: deleteCommand">
<i class="fontastic icon-white">🗑</i>
</a>
<span class="saved-text hide-on-mobile" data-bind="text: savedTimeText"></span>
<span class="saved-text hide-mobile" data-bind="text: savedTimeText"></span>
</div>
<div class="modal-body">
<div class="b-header g-ui-user-select-none">

View file

@ -19,15 +19,11 @@
</div>
<div class="btn-group">
<a class="btn button-delete" data-bind="command: deleteCommand">
<i class="fontastic">🗑</i>
</a>
<a class="btn button-delete fontastic" data-bind="command: deleteCommand">🗑</a>
</div>
<div class="btn-group dropdown colored-toggle" data-bind="registerBootstrapDropdown: true">
<a id="contacts-more-dropdown-id" class="btn dropdown-toggle" href="#" tabindex="-1" data-toggle="dropdown">
<i class="fontastic" data-bind="css: {'icon-spinner': contacts.importing() || contacts.syncing()}"></i>
</a>
<a id="contacts-more-dropdown-id" class="btn dropdown-toggle fontastic" href="#" tabindex="-1" data-toggle="dropdown" data-bind="css: {'icon-spinner': contacts.importing() || contacts.syncing()}"></a>
<ul class="dropdown-menu g-ui-menu right-edge" role="menu" aria-labelledby="contacts-more-dropdown-id">
<li class="e-item" role="presentation">
<a class="e-link menuitem" href="#" tabindex="-1" data-bind="initDom: importUploaderButton">
@ -35,13 +31,13 @@
<span data-i18n="CONTACTS/BUTTON_IMPORT"></span>
</a>
</li>
<li class="e-item dividerbar hide-mobile" role="presentation">
<li class="e-item dividerbar" role="presentation">
<a class="e-link menuitem" href="#" tabindex="-1" data-bind="click: exportCsv">
<i data-bind="css: {'icon-export': !contacts.exportingCsv(), 'icon-spinner': contacts.exportingCsv}"></i>
<span data-i18n="CONTACTS/BUTTON_EXPORT_CSV"></span>
</a>
</li>
<li class="e-item hide-mobile" role="presentation">
<li class="e-item" role="presentation">
<a class="e-link menuitem" href="#" tabindex="-1" data-bind="click: exportVcf">
<i data-bind="css: {'icon-export': !contacts.exportingVcf(), 'icon-spinner': contacts.exportingVcf}"></i>
<span data-i18n="CONTACTS/BUTTON_EXPORT_VCARD"></span>
@ -79,16 +75,11 @@
</div>
<div class="e-contact-foreach g-ui-user-select-none" data-bind="foreach: contacts, visible: 0 < contacts().length">
<div class="e-contact-item g-ui-user-select-none" data-bind="css: lineAsCss()">
<div class="sidebarParent">
<div class="checkboxItem fontastic" data-bind="text: checked() ? '☑' : '☐'"></div>
<div class="nameParent actionHandle">
<span class="listName" data-bind="text: display"></span>
&nbsp;
</div>
<div class="wrapper">
<div class="checkboxItem fontastic" data-bind="text: checked() ? '☑' : '☐'"></div>
<div class="nameParent actionHandle">
<span class="listName" data-bind="text: display"></span>
&nbsp;
</div>
</div>
</div>
</div>
</div>

View file

@ -75,9 +75,7 @@
</a>
</td>
<td>
<span class="delete-filter" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oFilter) { $root.filterForDeletion(oFilter); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-filter fontastic" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oFilter) { $root.filterForDeletion(oFilter); }">🗑</span>
</td>
</tr>
</tbody>

View file

@ -35,9 +35,7 @@
</a>
</td>
<td>
<span class="delete-account" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oAccount) { $root.accountForDeletion(oAccount); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-account fontastic" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oAccount) { $root.accountForDeletion(oAccount); }">🗑</span>
</td>
</tr>
</tbody>
@ -83,9 +81,7 @@
</a>
</td>
<td>
<span class="delete-identity" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oIdentity) { $root.identityForDeletion(oIdentity); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-identity fontastic" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oIdentity) { $root.identityForDeletion(oIdentity); }">🗑</span>
</td>
</tr>
</tbody>

View file

@ -36,9 +36,7 @@
</a>
</td>
<td>
<span class="delete-script" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oScript) { $root.scriptForDeletion(oScript); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-script fontastic" data-bind="visible: !deleteAccess() && canBeDeleted(), click: function (oScript) { $root.scriptForDeletion(oScript); }">🗑</span>
</td>
</tr>
</tbody>

View file

@ -15,9 +15,7 @@
<div class="controls">
<input type="text" class="span5" data-bind="value: actionValueFourth"
data-i18n="[placeholder]POPUPS_FILTER/VACATION_RECIPIENTS_LABEL" />
<button class="btn setRecipientsBtn" data-bind="click: setRecipients">
<i class="fontastic"></i>
</button>
<button class="btn setRecipientsBtn fontastic" data-bind="click: setRecipients"></button>
</div>
</div>
<div class="control-group" style="margin-bottom: 0">

View file

@ -5,8 +5,6 @@
&nbsp;
<input class="span3" type="text" data-bind="value: value" />
&nbsp;
<span class="delete-action button-delete pull-right" style="margin-top: 5px;"
data-bind="click: function (oCondition) { $root.removeCondition(oCondition); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-action button-delete pull-right fontastic" style="margin-top: 5px;"
data-bind="click: function (oCondition) { $root.removeCondition(oCondition); }">🗑</span>
</div>

View file

@ -5,8 +5,6 @@
&nbsp;
<input class="span3" type="text" data-bind="value: value" />
&nbsp;
<span class="delete-action button-delete pull-right" style="margin-top: 5px;"
data-bind="click: function (oCondition) { $root.removeCondition(oCondition); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-action button-delete pull-right fontastic" style="margin-top: 5px;"
data-bind="click: function (oCondition) { $root.removeCondition(oCondition); }">🗑</span>
</div>

View file

@ -7,8 +7,6 @@
&nbsp;
<input class="span3" type="text" data-bind="value: value" />
&nbsp;
<span class="delete-action button-delete pull-right" style="margin-top: 5px;"
data-bind="click: function (oCondition) { $root.removeCondition(oCondition); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-action button-delete pull-right fontastic" style="margin-top: 5px;"
data-bind="click: function (oCondition) { $root.removeCondition(oCondition); }">🗑</span>
</div>

View file

@ -5,8 +5,6 @@
&nbsp;
<input class="span3" type="text" data-bind="value: value" />
&nbsp;
<span class="delete-action button-delete pull-right" style="margin-top: 5px;"
data-bind="click: function (oCondition) { $root.removeCondition(oCondition); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-action button-delete pull-right fontastic" style="margin-top: 5px;"
data-bind="click: function (oCondition) { $root.removeCondition(oCondition); }">🗑</span>
</div>

View file

@ -85,7 +85,7 @@
value: showImages
}
}"></div>
<div class="hide-on-mobile" data-bind="component: {
<div class="hide-mobile" data-bind="component: {
name: 'Checkbox',
params: {
label: 'SETTINGS_GENERAL/LABEL_USE_CHECKBOXES_IN_LIST',

View file

@ -37,9 +37,7 @@
<!-- ko foreach: openpgpkeysPrivate -->
<tr class="open-pgp-key-item">
<td>
<span class="open-pgp-key-img" data-i18n="[title]SETTINGS_OPEN_PGP/TITLE_PRIVATE">
<i class="fontastic">🔒</i>
</span>
<span class="open-pgp-key-img fontastic" data-i18n="[title]SETTINGS_OPEN_PGP/TITLE_PRIVATE">🔒</span>
<span class="open-pgp-key-user">
<!-- ko foreach: users -->
<div class="open-pgp-key-user-address" data-bind="text: $data"></div>
@ -50,23 +48,17 @@
</a>
</td>
<td>
<span class="delete-open-pgp-key" data-bind="visible: !deleteAccess(), click: function (openPgpKey) { $root.openPgpKeyForDeletion(openPgpKey); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-open-pgp-key fontastic" data-bind="visible: !deleteAccess(), click: function (openPgpKey) { $root.openPgpKeyForDeletion(openPgpKey); }">🗑</span>
</td>
<td>
<span class="view-open-pgp-key" data-bind="click: function (openPgpKey) { $root.viewOpenPgpKey(openPgpKey); }">
<i class="fontastic">👁</i>
</span>
<span class="view-open-pgp-key fontastic" data-bind="click: function (openPgpKey) { $root.viewOpenPgpKey(openPgpKey); }">👁</span>
</td>
</tr>
<!-- /ko -->
<!-- ko foreach: openpgpkeysPublic -->
<tr class="open-pgp-key-item">
<td>
<span class="open-pgp-key-img" data-i18n="[title]SETTINGS_OPEN_PGP/TITLE_PUBLIC">
<i class="fontastic">🔑</i>
</span>
<span class="open-pgp-key-img fontastic" data-i18n="[title]SETTINGS_OPEN_PGP/TITLE_PUBLIC">🔑</span>
<span class="open-pgp-key-user">
<!-- ko foreach: users -->
<div class="open-pgp-key-user-address">
@ -79,14 +71,10 @@
</a>
</td>
<td>
<span class="delete-open-pgp-key" data-bind="visible: !deleteAccess(), click: function (openPgpKey) { $root.openPgpKeyForDeletion(openPgpKey); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-open-pgp-key fontastic" data-bind="visible: !deleteAccess(), click: function (openPgpKey) { $root.openPgpKeyForDeletion(openPgpKey); }">🗑</span>
</td>
<td>
<span class="view-open-pgp-key" data-bind="click: function (openPgpKey) { $root.viewOpenPgpKey(openPgpKey); }">
<i class="fontastic">👁</i>
</span>
<span class="view-open-pgp-key fontastic" data-bind="click: function (openPgpKey) { $root.viewOpenPgpKey(openPgpKey); }">👁</span>
</td>
</tr>
<!-- /ko -->

View file

@ -1,12 +1,12 @@
<div class="b-settings b-settins-right">
<div class="b-toolbar" style="padding-left: 0">
<div class="btn-toolbar" style="margin-top: 2px;">
<div class="btn-group" data-bind="visible: mobile && leftPanelDisabled()">
<div class="btn-group show-mobile" data-bind="visible: leftPanelDisabled()">
<a class="btn btn-thin-2" data-bind="click: showLeft">
<i class="icon-right-middle"></i>
</a>
</div>
<div class="btn-group" data-bind="visible: mobile && !leftPanelDisabled()" style="margin-left: -1px">
<div class="btn-group show-mobile" data-bind="visible: !leftPanelDisabled()" style="margin-left: -1px">
<a class="btn btn-thin-2" data-bind="click: hideLeft">
<i class="icon-left-middle"></i>
</a>

View file

@ -34,9 +34,7 @@
</a>
</td>
<td>
<span class="delete-template" data-bind="visible: !deleteAccess(), click: function (oTemplate) { $root.templateForDeletion(oTemplate); }">
<i class="fontastic">🗑</i>
</span>
<span class="delete-template fontastic" data-bind="visible: !deleteAccess(), click: function (oTemplate) { $root.templateForDeletion(oTemplate); }">🗑</span>
</td>
</tr>
</tbody>

View file

@ -10,7 +10,7 @@
</div>
<i class="stopIcon fontastic"></i>
</div>
<div class="accountPlace hide-on-mobile" data-bind="text: emailTitle()"></div>
<div class="accountPlace hide-mobile" data-bind="text: emailTitle()"></div>
<div class="btn-group dropdown colored-toggle" data-bind="registerBootstrapDropdown: true, openDropdownTrigger: accountMenuDropdownTrigger">
<a id="top-system-dropdown-id" href="#" tabindex="-1" class="btn single btn-ellipsis btn-block dropdown-toggle system-dropdown" data-toggle="dropdown">
<i class="fontastic" data-bind="css: {'icon-spinner': accounts.loading()}">👤</i>
@ -64,13 +64,13 @@
<span data-i18n="TOP_TOOLBAR/BUTTON_HELP"></span>
</a>
</li>
<li class="e-item dividerbar" role="presentation" data-bind="visible: mobile">
<li class="e-item dividerbar show-mobile" role="presentation">
<a class="e-link menuitem" href="./?/DesktopVersion/" tabindex="-1">
<i class="fontastic">💻</i>
<span data-i18n="MOBILE/BUTTON_DESKTOP_VERSION"></span>
</a>
</li>
<li class="e-item dividerbar" role="presentation" data-bind="visible: !mobile">
<li class="e-item dividerbar hide-mobile" role="presentation">
<a class="e-link menuitem" href="./?/MobileVersion/" tabindex="-1">
<i class="fontastic">📱</i>
<span data-i18n="MOBILE/BUTTON_MOBILE_VERSION"></span>

View file

@ -4,7 +4,8 @@
--main-color: #333;
--main-bg-color: #e3e3e3;
--main-bg-image: none; // "images/background.png"
--main-bg-size: inherit;
--main-bg-size: auto;
--main-bg-repeat: repeat;
// LOADING
--loading-color: #000; // #ddd