summaryrefslogtreecommitdiffstats
path: root/lib/private/cache/file.php
blob: 8a6ef39f61bb8061e51184ee06916781ebe5257c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<?php
/**
 * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */

namespace OC\Cache;

class File {
	protected $storage;
	protected function getStorage() {
		if (isset($this->storage)) {
			return $this->storage;
		}
		if(\OC_User::isLoggedIn()) {
			\OC\Files\Filesystem::initMountPoints(\OC_User::getUser());
			$subdir = 'cache';
			$view = new \OC\Files\View('/' . \OC_User::getUser());
			if(!$view->file_exists($subdir)) {
				$view->mkdir($subdir);
			}
			$this->storage = new \OC\Files\View('/' . \OC_User::getUser().'/'.$subdir);
			return $this->storage;
		}else{
			\OC_Log::write('core', 'Can\'t get cache storage, user not logged in', \OC_Log::ERROR);
			return false;
		}
	}

	/**
	 * @param string $key
	 */
	public function get($key) {
		$result = null;
		$proxyStatus = \OC_FileProxy::$enabled;
		\OC_FileProxy::$enabled = false;
		if ($this->hasKey($key)) {
			$storage = $this->getStorage();
			$result = $storage->file_get_contents($key);
		}
		\OC_FileProxy::$enabled = $proxyStatus;
		return $result;
	}

	/**
	 * Returns the size of the stored/cached data
	 *
	 * @param $key
	 * @return int
	 */
	public function size($key) {
		$result = 0;
		$proxyStatus = \OC_FileProxy::$enabled;
		\OC_FileProxy::$enabled = false;
		if ($this->hasKey($key)) {
			$storage = $this->getStorage();
			$result = $storage->filesize($key);
		}
		\OC_FileProxy::$enabled = $proxyStatus;
		return $result;
	}

	/**
	 * @param string $key
	 */
	public function set($key, $value, $ttl=0) {
		$storage = $this->getStorage();
		$result = false;
		$proxyStatus = \OC_FileProxy::$enabled;
		\OC_FileProxy::$enabled = false;
		if ($storage and $storage->file_put_contents($key, $value)) {
			if ($ttl === 0) {
				$ttl = 86400; // 60*60*24
			}
			$result = $storage->touch($key, time() + $ttl);
		}
		\OC_FileProxy::$enabled = $proxyStatus;
		return $result;
	}

	public function hasKey($key) {
		$storage = $this->getStorage();
		if ($storage && $storage->is_file($key)) {
			$mtime = $storage->filemtime($key);
			if ($mtime < time()) {
				$storage->unlink($key);
				return false;
			}
			return true;
		}
		return false;
	}

	/**
	 * @param string $key
	 */
	public function remove($key) {
		$storage = $this->getStorage();
		if(!$storage) {
			return false;
		}
		return $storage->unlink($key);
	}

	public function clear($prefix='') {
		$storage = $this->getStorage();
		if($storage and $storage->is_dir('/')) {
			$dh=$storage->opendir('/');
			if(is_resource($dh)) {
				while (($file = readdir($dh)) !== false) {
					if($file!='.' and $file!='..' and ($prefix==='' || strpos($file, $prefix) === 0)) {
						$storage->unlink('/'.$file);
					}
				}
			}
		}
		return true;
	}

	public function gc() {
		$storage = $this->getStorage();
		if($storage and $storage->is_dir('/')) {
			$now = time();
			$dh=$storage->opendir('/');
			if(!is_resource($dh)) {
				return null;
			}
			while (($file = readdir($dh)) !== false) {
				if($file!='.' and $file!='..') {
					$mtime = $storage->filemtime('/'.$file);
					if ($mtime < $now) {
						$storage->unlink('/'.$file);
					}
				}
			}
		}
	}

	public static function loginListener() {
		$c = new self();
		$c->gc();
	}
}
#n860'>860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
/**
 * @copyright Copyright (c) 2016-2017, John Molakvoæ <skjnldsv@protonmail.com>
 * @copyright Copyright (c) 2016, Julius Haertl <jus@bitgrid.net>
 * @copyright Copyright (c) 2016, Morris Jobke <hey@morrisjobke.de>
 * @copyright Copyright (c) 2016, pgys <info@pexlab.space>
 * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch>
 * @copyright Copyright (c) 2016, Stefan Weil <sw@weilnetz.de>
 * @copyright Copyright (c) 2016, Roeland Jago Douma <rullzer@owncloud.com>
 * @copyright Copyright (c) 2016, jowi <sjw@gmx.ch>
 * @copyright Copyright (c) 2015, Hendrik Leppelsack <hendrik@leppelsack.de>
 * @copyright Copyright (c) 2015, Thomas Müller <thomas.mueller@tmit.eu>
 * @copyright Copyright (c) 2015, Vincent Petry <pvince81@owncloud.com>
 * @copyright Copyright (c) 2014-2017, Jan-Christoph Borchardt <hey@jancborchardt.net>
 *
 * @license GNU AGPL version 3 or any later version
 *
 */

/* BASE STYLING ---------------------------------------------------------- */

h2 {
	font-size: 20px;
	font-weight: 300;
	margin-bottom: 12px;
	line-height: 140%;
}

h3 {
	font-size: 15px;
	font-weight: 300;
	margin: 12px 0;
}

/* do not use italic typeface style, instead lighter color */
em {
	font-style: normal;
	opacity: .5;
}

dl {
	padding: 12px 0;
}

dt,
dd {
	display: inline-block;
	padding: 12px;
	padding-left: 0;
}

dt {
	width: 130px;
	white-space: nowrap;
	text-align: right;
}

kbd {
	padding: 4px 10px;
	border: 1px solid #ccc;
	box-shadow: 0 1px 0 rgba(0, 0, 0, .2);
	border-radius: $border-radius;
	display: inline-block;
	white-space: nowrap;
}


/* APP STYLING -------------------------------------------------------------- */

#app {
	height: 100%;
	width: 100%;
	* {
		box-sizing: border-box;
	}
}

/* APP-NAVIGATION ------------------------------------------------------------*/

/* Navigation: folder like structure */

#app-navigation {
	width: 250px;
	height: 100%;
	float: left;
	box-sizing: border-box;
	background-color: $color-main-background;
	padding-bottom: 44px;
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
	border-right: 1px solid $color-border;
	display: flex;
	flex-direction: column;
	li {
		position: relative;
	}
	> ul {
		position: relative;
		height: 100%;
		width: inherit;
		overflow-x: hidden;
		overflow-y: auto;
		box-sizing: border-box;
		display: flex;
		flex-direction: column;
		> li {
			display: inline-flex;
			flex-wrap: wrap;
			order: 1;
			flex-shrink: 0;

			/* Pinned-to-bottom entries */
			&.pinned {
				order: 2;
				&.first-pinned {
					margin-top: auto !important;
				}
			}

			> a,
			> .app-navigation-entry-deleted {
				/* Ugly hack for overriding the main entry link */
				padding-left: 44px !important;
			}
			> .app-navigation-entry-edit {
				/* Ugly hack for overriding the main entry link */
				/* align the input correctly with the link text
				   44px-6px padding for the input */
				padding-left: 38px !important;
			}

			&:focus,
			&:hover,
			&.active,
			a.selected {
				&,
				> a {
					opacity: 1;
					box-shadow: inset 2px 0 $color-primary;
				}
			}

			/* align loader */
			&.icon-loading-small:after {
				left: 22px;
				top: 22px;
			}

			/* hide and animate deletion/collapse of subitems */
			&.deleted,
			&.collapsible:not(.open) {
				> ul {
					opacity: 0;
					max-height: 0;
					/* bezier override the hide/slow effect due to the 2000 max-height */
					transition: max-height 1000ms cubic-bezier(0, 1, 0, 1),
								opacity 250ms ease-in-out;
				}
			}

			/* Second level nesting for lists */
			> ul {
				flex: 1 0 100%;
				padding-left: 62px;
				width: inherit;
				transition: max-height 2000ms ease-in-out,
							opacity 250ms ease-in-out;
				max-height: 9999px;
				opacity: 1;
				> li {
					display: inline-flex;
					flex-wrap: wrap;
					&:focus,
					&:hover,
					&.active,
					a.selected {
						&,
						> a {
							opacity: 1;
						}
					}

					/* align loader */
					&.icon-loading-small:after {
						left: -10px;
					}

					/* Submenu fix for icon */
					> a[class*='icon-'],
					> a[style*='background-image'],
					.app-navigation-entry-bullet {
						margin-left: -32px; /* 44px padding - 12px padding */
					}

					/* Submenu fix for bullet */
					> .app-navigation-entry-bullet {
						left: -32px;/* 44px padding - 12px padding */
					}
				}
			}
		}
		/* Menu and submenu */
		> li,
		> li > ul > li {
			position: relative;
			width: 100%;
			box-sizing: border-box;
			/* hide icons if loading */
			&.icon-loading-small {
				> a,
				> .app-navigation-entry-bullet {
					background: none !important;
				}
			}
			/* Main entry link */
			> a {
				background-size: 16px 16px;
				background-position: 14px center;
				background-repeat: no-repeat;
				display: block;
				justify-content: space-between;
				line-height: 44px;
				min-height: 44px;
				padding: 0 12px;
				overflow: hidden;
				box-sizing: border-box;
				white-space: nowrap;
				text-overflow: ellipsis;
				color: $color-main-text;
				opacity: .57;
				flex: 1 1 0;
				z-index: 100; /* above the bullet */
				/* TODO: forbid using img as icon in menu? */
				&:first-child img {
				    margin-right: 11px;
				    width: 16px;
				    margin-left: -30px;
				}

				/* counter can also be inside the link */
				> .app-navigation-entry-utils  {
					display: inline-block;
					float: right;
					.app-navigation-entry-utils-counter {
						padding-right: 0 !important;
					}
				}
			}
			/* Bullet icon */
			> .app-navigation-entry-bullet {
				position: absolute;
				display: block;
				margin: 16px;
				width: 12px;
				height: 12px;
				border: none;
				border-radius: 50%;
				cursor: pointer;
			}

			/* padding in case of icon or bullet */
			> a[class*='icon-'],
			> a[style*='background-image'] {
				padding-left: 44px;
			}

			/* popover fix the flex positionning of the li parent */
			> .app-navigation-entry-menu {
				top: 44px;
			}

			/* show edit/undo field if editing/deleted */
			&.editing .app-navigation-entry-edit {
				opacity: 1;
				z-index: 250;
			}
			&.deleted .app-navigation-entry-deleted {
				transform: translateX(0);
				z-index: 250;
			}
		}
	}
	&.hidden {
		display: none;
	}
	&.without-app-settings {
		padding-bottom: 0;
	}

	/**
	 * Button styling for menu, edit and undo
	 */
	.app-navigation-entry-utils .app-navigation-entry-utils-menu-button > button,
	.app-navigation-entry-deleted .app-navigation-entry-deleted-button {
		border: 0;
		opacity: 0.5;
		background-color: transparent;
		background-repeat: no-repeat;
		background-position: center;
		&:hover,
		&:focus {
			background-color: transparent;
			opacity: 1;
		}
	}

	/**
	 * Collapsible menus
	 */
	.collapsible {
		/* Fallback for old collapse button.
		   TODO: to be removed. Leaved here for retro compatibility */
		.collapse {
			opacity: 0;
			position: absolute;
			width: 44px;
			height: 44px;
			margin: 0;
			z-index: 110;
		}
		&:after {
			position: absolute;
			height: 44px;
			width: 44px;
			margin: 0;
			padding: 0;
			background: none;
			background-image: url('../img/actions/triangle-s.svg?v=1');
			background-size: 16px;
			background-repeat: no-repeat;
			background-position: center;
			border: none;
			border-radius: 0;
			outline: none !important;
			box-shadow: none;
			content: ' ';
			opacity: 0;
			-webkit-transform: rotate(-90deg);
			-ms-transform: rotate(-90deg);
			transform: rotate(-90deg);
		}

		/* force padding on link no matter if 'a' has an icon class */
		> a:first-child {
			padding-left: 44px;
		}
		&:after,
		> a {
			transition: background 100ms ease-in-out,
						transform 250ms ease-in-out,
						opacity 100ms ease-in-out;
		}
		&:hover > a,
		&:focus > a {
			background-position-x: -50px;
		}
		&:hover,
		&:focus {
			&:after {
				opacity: 1;
			}
		}
		&.open {
			&:after {
				-webkit-transform: rotate(0);
				-ms-transform: rotate(0);
				transform: rotate(0);
			}
		}
	}

	/**
	 * App navigation utils, buttons and counters for drop down menu
	 */
	.app-navigation-entry-utils {
		flex: 0 1 auto;
		ul {
			display: flex !important;
			align-items: center;
			justify-content: flex-end;
		}
		li {
			width: 44px !important;
			height: 44px;
		}
		button {
			height: 100%;
			width: 100%;
			margin: 0;
			box-shadow: none;
		}
		.app-navigation-entry-utils-menu-button {
			/* Prevent bg img override if an icon class is set */
			button:not([class^='icon-']):not([class*=' icon-']) {
				background-image: url('../img/actions/more.svg?v=1');
			}
			&:hover button,
			&:focus button {
				background-color: transparent;
				opacity: 1;
			}
		}
		.app-navigation-entry-utils-counter {
			overflow: hidden;
			text-align: right;
			font-size: 9pt;
			line-height: 44px;
			padding: 0 12px; /* Same padding as all li > a in the app-navigation */
		}
	}

	/**
	 * Editable entries
	 */
	.app-navigation-entry-edit {
		padding-left: 5px;
		padding-right: 5px;
		display: block;
		width: calc(100% - 1px); /* Avoid border overlapping */
		transition: opacity 250ms ease-in-out;
		opacity: 0;
		position: absolute;
		background-color: $color-main-background;
		z-index: -1;
		form,
		div {
			display: inline-flex;
			width: 100%;
		}
		input {
			padding: 5px;
			margin-right: 0;
			height: 38px;
			&:hover {
				/* overlapp borders */
				z-index: 1;
			}
		}
		input[type='text'] {
			width: 100%;
			min-width: 0; /* firefox hack: override auto */
			border-bottom-right-radius: 0;
			border-top-right-radius: 0;
		}
		button,
		input:not([type='text']) {
			width: 36px;
			height: 38px;
			flex: 0 0 36px;
			&:not(:last-child) {
				border-radius: 0;
			}
			&:not(:first-child) {
				margin-left: -1px;
			}
			&:last-child {
				border-bottom-left-radius: 0;
				border-top-left-radius: 0;
			}
		}
	}

	/**
	 * Deleted entries with undo button
	 */
	.app-navigation-entry-deleted {
		display: inline-flex;
		padding-left: 12px;
		transform: translateX(250px);
		.app-navigation-entry-deleted-description {
			position: relative;
			white-space: nowrap;
			text-overflow: ellipsis;
			overflow: hidden;
			flex: 1 1 0;
			line-height: 44px;
		}
		.app-navigation-entry-deleted-button {
			margin: 0;
			height: 44px;
			width: 44px;
			line-height: 44px;
			&:hover, &:focus {
				opacity: 1;
			}
		}
	}

	/**
	 * Common rules for animation of undo and edit entries
	 */
	.app-navigation-entry-edit,
	.app-navigation-entry-deleted  {
		width: calc(100% - 1px); /* Avoid border overlapping */
		transition: transform 250ms ease-in-out,
					opacity 250ms ease-in-out,
					z-index 250ms ease-in-out;
		position: absolute;
		background-color: $color-main-background;
		box-sizing: border-box;
	}

	/**
	 * drag and drop
	 */
	.drag-and-drop {
		-webkit-transition: padding-bottom 500ms ease 0s;
		transition: padding-bottom 500ms ease 0s;
		padding-bottom: 40px;
	}

	.error {
		color: $color-error;
	}
	.app-navigation-separator {
		border-bottom: 1px solid nc-lighten($color-main-text, 86%);
	}

	.app-navigation-entry-utils ul,
	.app-navigation-entry-menu ul {
		list-style-type: none;
	}
}

/* APP-CONTENT ---------------------------------------------------------------*/
/* Part where the content will be loaded into */
#app-content {
	position: relative;
	height: 100%;
	overflow-y: auto;
	/* no top border for first settings item */
	> .section:first-child {
		border-top: none;
	}
	&.with-app-sidebar {
		margin-right: 27%;
	}
}

#app-content-wrapper {
	min-width: 100%;
	min-height: 100%;
}

/* APP-SIDEBAR ----------------------------------------------------------------*/

/*
	Sidebar: a sidebar to be used within #app-content
	 have it as first element within app-content in order to shrink other
	 sibling containers properly. Compare Files app for example.
*/
#app-sidebar {
	position: fixed;
	top: 45px;
	right: 0;
	left: auto;
	bottom: 0;
	width: 27%;
	min-width: 300px;
	display: block;
	background: $color-main-background;
	border-left: 1px solid $color-border;
	-webkit-transition: margin-right 300ms;
	transition: margin-right 300ms;
	overflow-x: hidden;
	overflow-y: auto;
	visibility: visible;
	z-index: 500;
	&.disappear {
		visibility: hidden;
	}
}

/* APP-SETTINGS ---------------------------------------------------------------*/

/* settings area */
#app-settings {
	position: fixed;
	width: 250px;
	/* change to 100% when layout positions are absolute */
	bottom: 0;
	z-index: 140;
	&.open,
	&.opened {
		#app-settings-content {
			display: block;
		}
	}
}

#app-settings-content {
	display: none;
	padding: 10px;
	background-color: $color-main-background;
	/* restrict height of settings and make scrollable */
	max-height: 300px;
	overflow-y: auto;
	border-right: 1px solid $color-border;
	width: 250px;
	box-sizing: border-box;

	/* display input fields at full width */
	input[type='text'] {
		width: 93%;
	}

	.info-text {
		padding: 5px 0 7px 22px;
		color: rgba($color-main-text, .4);
	}
	input {
		&[type='checkbox'],
		&[type='radio'] {
			&.radio,
			&.checkbox {
				+ label {
					display: inline-block;
					width: 100%;
					padding: 5px 0;
				}
			}
		}
	}
}

#app-settings-header {
	border-right: 1px solid $color-border;
	width: 250px;
	box-sizing: border-box;
	background-color: $color-main-background;
}

.settings-button {
	display: block;
	height: 44px;
	width: 100%;
	padding: 0;
	margin: 0;
	background-color: $color-main-background;
	background-image: url('../img/actions/settings-dark.svg?v=1');
	background-position: 14px center;
	background-repeat: no-repeat;
	box-shadow: none;
	border: 0;
	border-radius: 0;
	text-align: left;
	padding-left: 42px;
	font-weight: 400;

	/* like app-navigation a */
	color: $color-main-text;
	opacity: .57;

	&.opened,
	&:hover {
		background-color: $color-main-background;
		opacity: 1;
		box-shadow: inset 2px 0 $color-primary;
	}
}

/* GENERAL SECTION ---------------------------------------------------------- */
.section {
	display: block;
	padding: 30px;
	color: nc-lighten($color-main-text, 33%);
	margin-bottom: 24px;
	&.hidden {
		display: none !important;
	}
	/* slight position correction of checkboxes and radio buttons */
	input {
		&[type='checkbox'],
		&[type='radio'] {
			vertical-align: -2px;
			margin-right: 4px;
		}
	}
}
.sub-section {
	position: relative;
	margin-top: 10px;
	margin-left: 27px;
	margin-bottom: 10px;
}

.appear {
	opacity: 1;
	-webkit-transition: opacity 500ms ease 0s;
	-moz-transition: opacity 500ms ease 0s;
	-ms-transition: opacity 500ms ease 0s;
	-o-transition: opacity 500ms ease 0s;
	transition: opacity 500ms ease 0s;
	&.transparent {
		opacity: 0;
	}
}

/* DROPDOWN ----------------------------------------------------------------- */
.dropdown {
	background: nc-darken($color-main-background, 8%);
	border-bottom-left-radius: 5px;
	border-bottom-right-radius: 5px;
	box-shadow: 0 1px 1px $color-box-shadow;
	display: block;
	margin-right: 0;
	position: absolute;
	right: 0;
	width: 420px;
	z-index: 500;
	padding: 16px;
}

/* TABS --------------------------------------------------------------------- */
.tabHeaders {
	display: inline-block;
	margin: 15px;
	.tabHeader {
		float: left;
		padding: 5px;
		cursor: pointer;
		color: nc-lighten($color-main-text, 33%);
		margin-bottom: 1px;
		a {
			color: nc-lighten($color-main-text, 33%);
			margin-bottom: 1px;
		}
		&.selected {
			font-weight: 600;
			border-bottom: 1px solid nc-lighten($color-main-text, 20%);
		}
		&:hover {
			border-bottom: 1px solid nc-lighten($color-main-text, 20%);
		}
		&.selected, &:hover {
			margin-bottom: 0px;
			color: $color-main-text;
			a {
				margin-bottom: 0px;
				color: $color-main-text;
			}
		}
	}
}
.tabsContainer {
	clear: left;
	.tab {
		padding: 0 15px 15px;
	}
}

/* POPOVER MENU ------------------------------------------------------------- */
.ie,
.edge {
	.bubble, .bubble:after,
	.popovermenu, .popovermenu:after,
	#app-navigation .app-navigation-entry-menu,
	#app-navigation .app-navigation-entry-menu:after {
		border: 1px solid $color-border;
	}
}

.bubble,
.app-navigation-entry-menu,
.popovermenu {
	position: absolute;
	background-color: $color-main-background;
	color: $color-main-text;
	border-radius: $border-radius;
	z-index: 110;
	margin: 5px;
	margin-top: -5px;
	right: 0;
	filter: drop-shadow(0 1px 3px $color-box-shadow);
	display: none;

	&:after {
		bottom: 100%;
	 /* Min-width of popover is 36px and arrow width is 20px
		wich leaves us 8px right and 8px left */
		right: 8px;
		/* change this to adjust the arrow position */
		border: solid transparent;
		content: ' ';
		height: 0;
		width: 0;
		position: absolute;
		pointer-events: none;
		border-bottom-color: $color-main-background;
		border-width: 10px;
	}
	/* Center the popover */
	&.menu-center {
		transform: translateX(50%);
		right: 50%;
		margin-right: 0;
		&:after {
			right: 50%;
			transform: translateX(50%);
		}
	}
	/* Align the popover to the left */
	&.menu-left {
		right: auto;
		left: 0;
		margin-right: 0;
		&:after {
			left: 6px;
			right: auto;
		}
	}

	&.open {
		display: block;
	}

	ul {
		/* Overwrite #app-navigation > ul ul */
		display: flex !important;
		flex-direction: column;
	}
	li {
		display: flex;
		flex: 0 0 auto;
		> button,
		> a,
		> .menuitem {
			cursor: pointer;
			line-height: 36px;
			border: 0;
			background-color: transparent;
			display: flex;
			align-items: center;
			width: auto;
			height: auto;
			margin: 0;
			font-weight: 300;
			box-shadow: none;
			width: 100%;
			color: $color-main-text;
			/* Override the app-navigation li opacity */
			opacity: .7 !important;
			[class^='icon-'],
			[class*=' icon-'],
			&[class^='icon-'],
			&[class*=' icon-'] {
				min-width: 0; /* Overwrite icons*/
				min-height: 0;
				background-position: 10px center;
				background-size: 16px;
			}
			[class^='icon-'],
			[class*=' icon-'] {
				/* Keep padding to define the width to
				 assure correct position of a possible text */
				padding: 18px 0 18px 36px;
			}
			&[class^='icon-'],
			&[class*=' icon-'] {
				padding: 0 10px 0 36px !important;
			}
			&:hover, &:focus, &.active {
				opacity: 1 !important;
			}
			/* prevent .action class to break the design */
			&.action {
				padding: inherit !important;
			}
			> span {
				cursor: pointer;
				white-space: nowrap;
			}
			> p {
				width: 150px;
				line-height: 1.6em;
				padding: 8px 0;
			}
			/* Add padding if contains icon+text */
			&:not(:empty) {
				padding-right: 10px !important;
			}
			> img {
				width: 16px;
				padding: 0 10px;
			}
			> input.checkbox + label {
				padding: 0 !important;
				&::before {
					margin: -2px 12px 0;
				}
			}
			> input.radio + label {
				padding: 0 !important;
				&::before {
					margin: -2px 11px 0;
				}
			}
		}
		> button {
			padding: 0;
			span {
				opacity: 1;
			}
		}

	}
}


#app-content-wrapper {
	display: flex;
}
.app-content-list {
	width: 300px;
	height: 100%;
	overflow-x: hidden;
	overflow-y: auto;
	border-right: 1px solid nc-darken($color-main-background, 8%);
	display: flex;
	flex-direction: column;
	transition: transform 250ms ease-in-out;

	.app-content-list-item {
		position: relative;
		height: 68px;
		border-top: 1px solid nc-darken($color-main-background, 8%);
		cursor: pointer;
		padding: 10px 7px;
		display: flex;
		flex-wrap: wrap;
		align-items: center;

		&:hover, &:focus,
		&.active {
			background-color: nc-darken($color-main-background, 6%);
		}

		.app-content-list-item-icon {
			position: absolute;
			left: 6px;
			top: 14px;
			display: inline-block;
			height: 40px;
			width: 40px;
			line-height: 40px;
			border-radius: 50%;
			vertical-align: middle;
			margin-right: 10px;
			color: #fff;
			text-align: center;
			font-size: 1.5em;
			text-transform: capitalize;
			object-fit: cover;
			user-select: none;
		}

		.app-content-list-item-star {
			position: absolute;
			display: none; /* change to inline-block when we implement it */
			left: 16px;
			top: 28px;
			padding: 20px;
			background-size: 16px;
			z-index: 100;
		}

		.app-content-list-item-line-one,
		.app-content-list-item-line-two {
			display: block;
			padding-left: 50px;
			white-space: nowrap;
			overflow: hidden;
			text-overflow: ellipsis;
			order: 1;
			flex: 1 1 0;
			padding-right: 10px;
		}

		.app-content-list-item-line-two {
			opacity: .5;
			order: 3;
			flex: 1 0 calc(100% - 24px);
		}

		.app-content-list-item-details {
			order: 2;
			white-space: nowrap;
			overflow: hidden;
			text-overflow: ellipsis;
			max-width: 100px;
			opacity: 0.5;
			user-select: none;
		}

		[class^='icon-'],
		[class*=' icon-'] {
			order: 4;
			width: 24px;
			height: 24px;
			opacity: 0.3;
			&:hover, &:focus {
				opacity: 0.7;
			}
		}
	}
}
/* App content */
.app-content-detail {
	width: 70%;

	#app-navigation-toggle-back {
		display: none;
	}
}

/* Mobile width < 768px */
@media only screen and (max-width: 768px) {

	/* full width for message list on mobile */
	.app-content-list {
		width: 100%;
		background: $color-main-background;
		position: relative;
		z-index: 100;
	}

	/* overlay message detail on top of message list */
	.app-content-detail {
		background: $color-main-background;
		width: 100%;
		left: 0;
		height: 100%;
		top: 0;
		box-shadow: 0 0 100px rgba(100, 100, 100, .9);
		position: absolute;
	}

	/* Show app details page */
	#app-content.showdetails {
		#app-navigation-toggle {
			transform: translateX(-44px);
		}
		#app-navigation-toggle-back {
			position: fixed;
			display: inline-block !important;
			top: 45px;
			left: 0;
			width: 44px;
			height: 44px;
			z-index: 149;
			background-color: rgba(255, 255, 255, .7);
			cursor: pointer;
			opacity: .6;
			transform: rotate(90deg);
		}
		.app-content-list {
			transform: translateX(-100%);
		}
	}

	/* end of media query */
}