From e2a75fe7d0989a788b70c56d9bb5e917bcc1c6bb Mon Sep 17 00:00:00 2001
From: Francesco Andreuzzi <andreuzzi.francesco@gmail.com>
Date: Tue, 18 Jul 2017 22:00:56 +0200
Subject: [PATCH] 5.3i

---
 app/build.gradle                              |   9 +-
 app/src/main/AndroidManifest.xml              |  31 +-
 .../consolelauncher/LauncherActivity.java     | 131 ++++--
 .../andre/consolelauncher/MainManager.java    |   7 +-
 .../ohi/andre/consolelauncher/UIManager.java  | 298 ++++++++++++--
 .../commands/CommandAbstraction.java          |   2 +
 .../commands/CommandTuils.java                |  22 +-
 .../commands/main/raw/community.java          |  54 +++
 .../commands/main/raw/config.java             |  15 +-
 .../commands/main/raw/notifications.java      |  51 ++-
 .../commands/main/raw/restart.java            |   2 +-
 .../commands/main/raw/tutorial.java           |  59 +++
 .../commands/specific/ParamCommand.java       |   2 -
 .../commands/tuixt/TuixtActivity.java         |  25 +-
 .../consolelauncher/managers/AppsManager.java | 260 ++++++------
 .../managers/ContactManager.java              |  18 +-
 .../consolelauncher/managers/SkinManager.java |  22 +-
 .../managers/TerminalMAnager.java             | 149 ++++---
 .../managers/XMLPrefsManager.java             | 377 ++++++++++++++++--
 .../notifications/NotificationManager.java    | 218 ++++++++--
 .../notifications/NotificationService.java    |  86 +++-
 .../suggestions/SuggestionsManager.java       |   6 +-
 .../consolelauncher/tuils/KeeperService.java  |   3 +
 .../andre/consolelauncher/tuils/Sequence.java |  81 ++++
 .../tuils/SimpleMutableEntry.java             |  30 +-
 .../andre/consolelauncher/tuils/Tuils.java    | 199 ++++++++-
 app/src/main/res/layout/about_device_view.xml |  14 +-
 app/src/main/res/values/strings.xml           |  26 +-
 28 files changed, 1753 insertions(+), 444 deletions(-)
 create mode 100644 app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/community.java
 create mode 100644 app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/tutorial.java
 create mode 100644 app/src/main/java/ohi/andre/consolelauncher/tuils/Sequence.java

diff --git a/app/build.gradle b/app/build.gradle
index 457f2bc..22bac84 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -10,8 +10,8 @@ android {
         minSdkVersion 8
         targetSdkVersion 23
 
-        versionCode 95
-        versionName "5.3i"
+        versionCode 103
+        versionName "6.0a"
     }
 
     buildTypes {
@@ -34,10 +34,13 @@ android {
     }
 
     applicationVariants.all { variant ->
+        def vn = variant.versionName
+        def x = vn.substring(0,vn.length() - 1)
+
         variant.outputs.each { output ->
             output.outputFile = new File(
                     output.outputFile.parent,
-                    output.outputFile.name.replace("app-release.apk", "${variant.applicationId}_${variant.versionName}.apk"))
+                    output.outputFile.name.replace("app-release.apk", "${x}/${variant.applicationId}_${variant.versionName}_${new Date().format("dd-MM_hh.mm.ss")}.apk"))
         }
     }
 }
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0972875..a95b27f 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -39,26 +39,28 @@
         android:protectionLevel="normal" />
 
     <!-- features -->
-    <uses-feature
-        android:name="android.hardware.camera"
+    <uses-feature android:name="android.hardware.camera"
         android:required="false" />
-    <uses-feature
-        android:name="android.hardware.camera.flash"
+    <uses-feature android:name="android.hardware.camera.flash"
         android:required="false" />
-    <uses-feature
-        android:name="android.hardware.telephony"
+    <uses-feature android:name="android.hardware.camera.autofocus"
         android:required="false" />
-    <uses-feature
-        android:name="android.hardware.wifi"
+    <uses-feature android:name="android.hardware.telephony"
         android:required="false" />
-    <uses-feature
-        android:name="android.hardware.touchscreen"
+    <uses-feature android:name="android.hardware.wifi"
         android:required="false" />
-    <uses-feature
-        android:name="android.hardware.bluetooth"
+    <uses-feature android:name="android.hardware.touchscreen"
+        android:required="false" />
+    <uses-feature android:name="android.hardware.bluetooth"
         android:required="false" />
     <uses-feature android:name="android.hardware.location.gps"
         android:required="false"/>
+    <uses-feature android:name="android.hardware.location"
+        android:required="false"/>
+    <uses-feature android:name="android.hardware.location.network"
+        android:required="false"/>
+    <uses-feature android:name="android.hardware.audio.output"
+        android:required="false"/>
 
     <application
         android:allowBackup="true"
@@ -69,7 +71,7 @@
             android:name=".LauncherActivity"
             android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"
 
-            android:launchMode="singleTask"
+            android:launchMode="singleInstance"
             android:clearTaskOnLaunch="true"
             android:stateNotNeeded="true"
             android:resumeWhilePausing="true"
@@ -179,8 +181,7 @@
 
         <service android:name=".managers.notifications.NotificationService"
             android:label="@string/notification_reader"
-            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
-            android:stopWithTask="true">
+            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
 
             <intent-filter>
                 <action android:name="android.service.notification.NotificationListenerService" />
diff --git a/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java b/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java
index a0531e7..603517a 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/LauncherActivity.java
@@ -1,8 +1,6 @@
 package ohi.andre.consolelauncher;
 
 import android.Manifest;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -14,6 +12,7 @@ import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
 import android.provider.Settings;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.content.ContextCompat;
@@ -28,14 +27,23 @@ import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.widget.Toast;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
 import ohi.andre.consolelauncher.commands.main.MainPack;
 import ohi.andre.consolelauncher.commands.tuixt.TuixtActivity;
 import ohi.andre.consolelauncher.managers.ContactManager;
+import ohi.andre.consolelauncher.managers.TerminalManager;
 import ohi.andre.consolelauncher.managers.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.notifications.NotificationManager;
+import ohi.andre.consolelauncher.managers.notifications.NotificationService;
 import ohi.andre.consolelauncher.managers.suggestions.SuggestionsManager;
 import ohi.andre.consolelauncher.tuils.Assist;
 import ohi.andre.consolelauncher.tuils.KeeperService;
+import ohi.andre.consolelauncher.tuils.StoppableThread;
 import ohi.andre.consolelauncher.tuils.Tuils;
 import ohi.andre.consolelauncher.tuils.interfaces.CommandExecuter;
 import ohi.andre.consolelauncher.tuils.interfaces.Inputable;
@@ -45,7 +53,7 @@ import ohi.andre.consolelauncher.tuils.stuff.PolicyReceiver;
 
 public class LauncherActivity extends AppCompatActivity implements Reloadable {
 
-    private final String FIRSTACCESS_KEY = "x1";
+    private final String FIRSTACCESS_KEY = "x3";
 
     public static final int COMMAND_REQUEST_PERMISSION = 10;
     public static final int STARTING_PERMISSION = 11;
@@ -108,17 +116,20 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
         @Override
         public void onOutput(String output) {
             try {
-                ui.setOutput(output);
+                ui.setOutput(output, TerminalManager.CATEGORY_OUTPUT);
             } catch (NullPointerException e) {
                 e.printStackTrace();
             }
         }
     };
 
+    static final boolean DEBUG = false;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        overridePendingTransition(0,0);
+
         if (isFinishing()) {
             return;
         }
@@ -138,12 +149,53 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
 
     private void finishOnCreate() {
 
-        SharedPreferences preferences = getPreferences(0);
-        boolean firstAccess = preferences.getBoolean(FIRSTACCESS_KEY, true);
-        if (firstAccess) {
-            SharedPreferences.Editor editor = preferences.edit();
-            editor.putBoolean(FIRSTACCESS_KEY, false);
-            editor.commit();
+        Thread logger = null;
+        if(DEBUG) {
+            Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+                @Override
+                public void uncaughtException(Thread t, Throwable e) {
+                    try {
+                        e.printStackTrace(new PrintStream(new FileOutputStream(new File(Tuils.getFolder(), "crash.txt"), true)));
+                    } catch (FileNotFoundException e1) {}
+                }
+            });
+
+            final Thread c = Thread.currentThread();
+            logger = new StoppableThread() {
+
+                FileOutputStream stream;
+                final String newline = "###" + Tuils.NEWLINE;
+
+                @Override
+                public void run() {
+
+                    if(stream == null) {
+                        try {
+                            stream = new FileOutputStream(new File(Tuils.getFolder(), "hang.txt"));
+                        } catch (FileNotFoundException e) {
+                            return;
+                        }
+                    }
+
+                    if(Thread.currentThread().isInterrupted()) return;
+
+                    StackTraceElement[] stack = c.getStackTrace();
+                    for(StackTraceElement s : stack) {
+                        if(s.getClassName().startsWith("ohi.andre.consolelauncher"))
+                            try {
+                                stream.write( (s.getClassName() + " -> " + s.getMethodName() + ": " + s.getLineNumber() + Tuils.NEWLINE).getBytes());
+                            } catch (IOException e) {}
+                    }
+                    try {
+                        stream.write(newline.getBytes());
+                    } catch (IOException e) {}
+
+                    if(Thread.currentThread().isInterrupted()) return;
+
+                    run();
+                }
+            };
+            logger.start();
         }
 
         try {
@@ -184,7 +236,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
         }
 
         NotificationManager.create();
-        boolean notifications = XMLPrefsManager.get(boolean.class, NotificationManager.Options.enabled);
+        boolean notifications = XMLPrefsManager.get(boolean.class, NotificationManager.Options.show_notifications);
         if(notifications) {
             LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, new IntentFilter("Msg"));
             if(!Tuils.hasNotificationAccess(this)) {
@@ -209,7 +261,23 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
 
         if(fullscreen) Assist.assistActivity(this);
 
+        SharedPreferences preferences = getPreferences(0);
+        boolean firstAccess = preferences.getBoolean(FIRSTACCESS_KEY, true);
+        if (firstAccess) {
+            SharedPreferences.Editor editor = preferences.edit();
+            editor.putBoolean(FIRSTACCESS_KEY, false);
+            editor.commit();
+
+            ui.setOutput(getString(R.string.firsthelp_text), TerminalManager.CATEGORY_OUTPUT);
+            ui.setInput("tutorial");
+        }
+
         System.gc();
+
+        if(logger != null) {
+            logger.interrupt();
+            logger = null;
+        }
     }
 
     @Override
@@ -236,10 +304,16 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
         super.onDestroy();
 
         stopService(new Intent(this, KeeperService.class));
+        stopService(new Intent(this, NotificationService.class));
+        LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
+
+        overridePendingTransition(0,0);
 
         if(main != null) {
             main.destroy();
         }
+
+        System.exit(0);
     }
 
     @Override
@@ -264,14 +338,13 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
         runOnUiThread(new Runnable() {
             @Override
             public void run() {
-
-                Intent mStartActivity = new Intent(LauncherActivity.this, LauncherActivity.class);
-                int mPendingIntentId = 123456;
-                PendingIntent mPendingIntent = PendingIntent.getActivity(LauncherActivity.this, mPendingIntentId, mStartActivity,
-                        PendingIntent.FLAG_CANCEL_CURRENT);
-                AlarmManager mgr = (AlarmManager) LauncherActivity.this.getSystemService(Context.ALARM_SERVICE);
-                mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
-                System.exit(0);
+                Handler h = new Handler();
+                h.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        finish();
+                    }
+                }, 2 * 1000);
             }
         });
     }
@@ -307,7 +380,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
         if(suggestion != null) {
             if(suggestion.type == SuggestionsManager.Suggestion.TYPE_CONTACT) {
                 ContactManager.Contact contact = (ContactManager.Contact) suggestion.object;
-                contact.selectedNumber = item.getItemId();
+                contact.setSelectedNumber(item.getItemId());
 
                 in.in(suggestion.getText());
 
@@ -340,7 +413,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
                         MainPack info = main.getMainPack();
                         main.onCommand(info.lastCommand, null);
                     } else {
-                        ui.setOutput(getString(R.string.output_nopermissions));
+                        ui.setOutput(getString(R.string.output_nopermissions), TerminalManager.CATEGORY_OUTPUT);
                         main.sendPermissionNotGrantedWarning();
                     }
                     break;
@@ -359,7 +432,7 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
                     break;
                 case COMMAND_SUGGESTION_REQUEST_PERMISSION:
                     if (grantResults.length == 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
-                        ui.setOutput(getString(R.string.output_nopermissions));
+                        ui.setOutput(getString(R.string.output_nopermissions), TerminalManager.CATEGORY_OUTPUT);
                     }
                     break;
             }
@@ -377,17 +450,9 @@ public class LauncherActivity extends AppCompatActivity implements Reloadable {
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            String pack = intent.getStringExtra("package");
-            String title = intent.getStringExtra("title");
-            String text = intent.getStringExtra("text");
-            int color = intent.getIntExtra("color", -1);
-
-            if(ui != null) {
-                ui.setOutput(pack + ": " + (title == null ? Tuils.EMPTYSTRING : title + (text == null ? Tuils.EMPTYSTRING : " --- ")) + (text == null ? Tuils.EMPTYSTRING : text),
-                        color,
-                        false);
-            }
+            CharSequence text = intent.getCharSequenceExtra("text");
+
+            if(ui != null) ui.setOutput(text, TerminalManager.CATEGORY_NOTIFICATION);
         }
     };
-
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/MainManager.java b/app/src/main/java/ohi/andre/consolelauncher/MainManager.java
index fc90af8..f8a6bfa 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/MainManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/MainManager.java
@@ -8,8 +8,6 @@ import android.os.Handler;
 import android.os.Looper;
 import android.util.Log;
 
-import java.util.Arrays;
-
 import ohi.andre.consolelauncher.commands.Command;
 import ohi.andre.consolelauncher.commands.CommandGroup;
 import ohi.andre.consolelauncher.commands.CommandTuils;
@@ -21,7 +19,6 @@ import ohi.andre.consolelauncher.managers.AppsManager;
 import ohi.andre.consolelauncher.managers.ContactManager;
 import ohi.andre.consolelauncher.managers.MusicManager;
 import ohi.andre.consolelauncher.managers.XMLPrefsManager;
-import ohi.andre.consolelauncher.managers.notifications.NotificationManager;
 import ohi.andre.consolelauncher.tuils.ShellUtils;
 import ohi.andre.consolelauncher.tuils.StoppableThread;
 import ohi.andre.consolelauncher.tuils.Tuils;
@@ -301,7 +298,9 @@ public class MainManager {
 
             if(showAppHistory) out.onOutput("-->" + Tuils.SPACE + intent.getComponent().getClassName());
 
-            mContext.startActivity(intent);
+//            if(intent.getBooleanExtra("forResult", false)) ((Activity) mContext).startActivityForResult(intent, 0);
+//            else
+                mContext.startActivity(intent);
 
             return true;
         }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/UIManager.java b/app/src/main/java/ohi/andre/consolelauncher/UIManager.java
index e0f85d3..38d3974 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/UIManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/UIManager.java
@@ -27,6 +27,9 @@ import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
 
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
@@ -36,6 +39,7 @@ import ohi.andre.consolelauncher.managers.TerminalManager;
 import ohi.andre.consolelauncher.managers.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.suggestions.SuggestionRunnable;
 import ohi.andre.consolelauncher.managers.suggestions.SuggestionsManager;
+import ohi.andre.consolelauncher.tuils.Sequence;
 import ohi.andre.consolelauncher.tuils.StoppableThread;
 import ohi.andre.consolelauncher.tuils.Tuils;
 import ohi.andre.consolelauncher.tuils.interfaces.CommandExecuter;
@@ -47,7 +51,9 @@ public class UIManager implements OnTouchListener {
 
     private final int RAM_DELAY = 3000;
     private final int BATTERY_DELAY = 20 * 1000;
+//    private final int BATTERY_CHARGING_DELAY = 300;
     private final int TIME_DELAY = 1000;
+    private final int STORAGE_DELAY = 60 * 1000;
 
     protected Context mContext;
 
@@ -66,40 +72,204 @@ public class UIManager implements OnTouchListener {
     private TextView device;
     private TextView battery;
     private TextView time;
+    private TextView storage;
+
+    int mediumPercentage, lowPercentage;
+    String batteryFormat;
+//    boolean batteryCharging;
 
     private Runnable batteryRunnable = new Runnable() {
         @Override
         public void run() {
             int percentage = Tuils.getBatteryPercentage(mContext);
 
-            if(percentage >= 50 || !skinManager.manyColorsBattery) battery.setTextColor(skinManager.battery_color_high);
-            else if(percentage >= 10) battery.setTextColor(skinManager.battery_color_medium);
-            else battery.setTextColor(skinManager.battery_color_low);
+            if(skinManager.manyColorsBattery) {
+                if(percentage > mediumPercentage) battery.setTextColor(skinManager.battery_color_high);
+                else if(percentage > lowPercentage) battery.setTextColor(skinManager.battery_color_medium);
+                else battery.setTextColor(skinManager.battery_color_low);
+            } else {
+                battery.setTextColor(skinManager.battery_color_high);
+            }
+
+            if(batteryFormat == null) batteryFormat = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.battery_format);
 
-            battery.setText(percentage + "%");
+            String cp = batteryFormat.replaceAll("%[vV]", String.valueOf(percentage)).replaceAll("%[nN]", Tuils.NEWLINE);
+            battery.setText(cp);
 
             battery.postDelayed(batteryRunnable, BATTERY_DELAY);
         }
     };
 
-    private String format;
+//    private Runnable batteryChargingRunnable = new Runnable() {
+//
+//        int[] colors;
+//        int index = 0;
+//
+//        @Override
+//        public void run() {
+//            if(colors == null) {
+//                colors = new int[3];
+//                colors[0] = XMLPrefsManager.getColor(XMLPrefsManager.Theme.battery_color_high);
+//                colors[1] = XMLPrefsManager.getColor(XMLPrefsManager.Theme.battery_color_medium);
+//                colors[2] = XMLPrefsManager.getColor(XMLPrefsManager.Theme.battery_color_low);
+//            }
+//
+//            battery.setTextColor(colors[index++]);
+//            if(index >= colors.length) index = 0;
+//
+//            battery.postDelayed(this, BATTERY_CHARGING_DELAY);
+//        }
+//    };
+
+    private final String INT_AV = "%iav";
+    private final String INT_TOT = "%itot";
+    private final String EXT_AV = "%eav";
+    private final String EXT_TOT = "%etot";
+
+    private List<Pattern> storagePatterns;
+    private String storageFormat;
+    private Runnable storageRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if(storageFormat == null) storageFormat = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.storage_format);
+
+            if(storagePatterns == null) {
+                storagePatterns = new ArrayList<>();
+
+                storagePatterns.add(Pattern.compile(INT_AV + "tb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(INT_AV + "gb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(INT_AV + "mb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(INT_AV + "kb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(INT_AV + "b", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(INT_AV + "%", Pattern.CASE_INSENSITIVE));
+
+                storagePatterns.add(Pattern.compile(INT_TOT + "tb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(INT_TOT + "gb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(INT_TOT + "mb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(INT_TOT + "kb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(INT_TOT + "b", Pattern.CASE_INSENSITIVE));
+
+                storagePatterns.add(Pattern.compile(EXT_AV + "tb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(EXT_AV + "gb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(EXT_AV + "mb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(EXT_AV + "kb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(EXT_AV + "b", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(EXT_AV + "%", Pattern.CASE_INSENSITIVE));
+
+                storagePatterns.add(Pattern.compile(EXT_TOT + "tb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(EXT_TOT + "gb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(EXT_TOT + "mb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(EXT_TOT + "kb", Pattern.CASE_INSENSITIVE));
+                storagePatterns.add(Pattern.compile(EXT_TOT + "b", Pattern.CASE_INSENSITIVE));
+
+                storagePatterns.add(Pattern.compile("%n", Pattern.CASE_INSENSITIVE));
+            }
+
+            double iav = Tuils.getAvailableInternalMemorySize(Tuils.BYTE);
+            double itot = Tuils.getTotalInternalMemorySize(Tuils.BYTE);
+            double eav = Tuils.getAvailableExternalMemorySize(Tuils.BYTE);
+            double etot = Tuils.getTotalExternalMemorySize(Tuils.BYTE);
+
+            String copy = storageFormat;
+
+            copy = storagePatterns.get(0).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) iav, Tuils.TERA)));
+            copy = storagePatterns.get(1).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) iav, Tuils.GIGA)));
+            copy = storagePatterns.get(2).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) iav, Tuils.MEGA)));
+            copy = storagePatterns.get(3).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) iav, Tuils.KILO)));
+            copy = storagePatterns.get(4).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) iav, Tuils.BYTE)));
+            copy = storagePatterns.get(5).matcher(copy).replaceAll(String.valueOf(Tuils.percentage(iav, itot)));
+
+            copy = storagePatterns.get(6).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) itot, Tuils.TERA)));
+            copy = storagePatterns.get(7).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) itot, Tuils.GIGA)));
+            copy = storagePatterns.get(8).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) itot, Tuils.MEGA)));
+            copy = storagePatterns.get(9).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) itot, Tuils.KILO)));
+            copy = storagePatterns.get(10).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) itot, Tuils.BYTE)));
+
+            copy = storagePatterns.get(11).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) eav, Tuils.TERA)));
+            copy = storagePatterns.get(12).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) eav, Tuils.GIGA)));
+            copy = storagePatterns.get(14).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) eav, Tuils.MEGA)));
+            copy = storagePatterns.get(14).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) eav, Tuils.KILO)));
+            copy = storagePatterns.get(15).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) eav, Tuils.BYTE)));
+            copy = storagePatterns.get(16).matcher(copy).replaceAll(String.valueOf(Tuils.percentage(eav, etot)));
+
+            copy = storagePatterns.get(17).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) etot, Tuils.TERA)));
+            copy = storagePatterns.get(18).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) etot, Tuils.GIGA)));
+            copy = storagePatterns.get(19).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) etot, Tuils.MEGA)));
+            copy = storagePatterns.get(20).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) etot, Tuils.KILO)));
+            copy = storagePatterns.get(21).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) etot, Tuils.BYTE)));
+
+            copy = storagePatterns.get(22).matcher(copy).replaceAll(Tuils.NEWLINE);
+
+            storage.setText(copy);
+            storage.postDelayed(this, STORAGE_DELAY);
+        }
+    };
+
+    private String timeFormat;
     private Runnable timeRunnable = new Runnable() {
         @Override
         public void run() {
             Time t = new Time();
             t.setToNow();
 
-            time.setText(t.format(format));
+            time.setText(t.format(timeFormat));
             time.postDelayed(this, TIME_DELAY);
         }
     };
 
     private ActivityManager.MemoryInfo memory;
     private ActivityManager activityManager;
+
+    private final String AV = "%av";
+    private final String TOT = "%tot";
+
+    List<Pattern> ramPatterns;
+    String ramFormat;
     private Runnable ramRunnable = new Runnable() {
         @Override
         public void run() {
-            updateRamDetails();
+            if(ramFormat == null) ramFormat = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.ram_format);
+
+            if(ramPatterns == null) {
+                ramPatterns = new ArrayList<>();
+
+                ramPatterns.add(Pattern.compile(AV + "tb", Pattern.CASE_INSENSITIVE));
+                ramPatterns.add(Pattern.compile(AV + "gb", Pattern.CASE_INSENSITIVE));
+                ramPatterns.add(Pattern.compile(AV + "mb", Pattern.CASE_INSENSITIVE));
+                ramPatterns.add(Pattern.compile(AV + "kb", Pattern.CASE_INSENSITIVE));
+                ramPatterns.add(Pattern.compile(AV + "b", Pattern.CASE_INSENSITIVE));
+                ramPatterns.add(Pattern.compile(AV + "%", Pattern.CASE_INSENSITIVE));
+
+                ramPatterns.add(Pattern.compile(TOT + "tb", Pattern.CASE_INSENSITIVE));
+                ramPatterns.add(Pattern.compile(TOT + "gb", Pattern.CASE_INSENSITIVE));
+                ramPatterns.add(Pattern.compile(TOT + "mb", Pattern.CASE_INSENSITIVE));
+                ramPatterns.add(Pattern.compile(TOT + "kb", Pattern.CASE_INSENSITIVE));
+                ramPatterns.add(Pattern.compile(TOT + "b", Pattern.CASE_INSENSITIVE));
+
+                ramPatterns.add(Pattern.compile("%n", Pattern.CASE_INSENSITIVE));
+            }
+
+            String copy = ramFormat;
+
+            double av = Tuils.freeRam(activityManager, memory);
+            double tot = Tuils.totalRam() * 1024L;
+
+            copy = ramPatterns.get(0).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) av, Tuils.TERA)));
+            copy = ramPatterns.get(1).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) av, Tuils.GIGA)));
+            copy = ramPatterns.get(2).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) av, Tuils.MEGA)));
+            copy = ramPatterns.get(3).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) av, Tuils.KILO)));
+            copy = ramPatterns.get(4).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) av, Tuils.BYTE)));
+            copy = ramPatterns.get(5).matcher(copy).replaceAll(String.valueOf(Tuils.percentage(av, tot)));
+
+            copy = ramPatterns.get(6).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) tot, Tuils.TERA)));
+            copy = ramPatterns.get(7).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) tot, Tuils.GIGA)));
+            copy = ramPatterns.get(8).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) tot, Tuils.MEGA)));
+            copy = ramPatterns.get(9).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) tot, Tuils.KILO)));
+            copy = ramPatterns.get(10).matcher(copy).replaceAll(String.valueOf(Tuils.formatSize((long) tot, Tuils.BYTE)));
+
+            copy = ramPatterns.get(11).matcher(copy).replaceAll(Tuils.NEWLINE);
+
+            ram.setText(copy);
             ram.postDelayed(this, RAM_DELAY);
         }
     };
@@ -389,10 +559,44 @@ public class UIManager implements OnTouchListener {
             });
         }
 
-        ram = (TextView) rootView.findViewById(R.id.ram_tv);
-        device = (TextView) rootView.findViewById(R.id.deviceinfo_tv);
-        battery = (TextView) rootView.findViewById(R.id.battery_tv);
-        time = (TextView) rootView.findViewById(R.id.time_tv);
+        TextView[] ts = {
+                (TextView) rootView.findViewById(R.id.tv0),
+                (TextView) rootView.findViewById(R.id.tv1),
+                (TextView) rootView.findViewById(R.id.tv2),
+                (TextView) rootView.findViewById(R.id.tv3),
+                (TextView) rootView.findViewById(R.id.tv4)
+        };
+
+        int ramIndex = XMLPrefsManager.get(int.class, XMLPrefsManager.Ui.ram_index);
+        int deviceIndex = XMLPrefsManager.get(int.class, XMLPrefsManager.Ui.device_index);
+        int batteryIndex = XMLPrefsManager.get(int.class, XMLPrefsManager.Ui.battery_index);
+        int timeIndex = XMLPrefsManager.get(int.class, XMLPrefsManager.Ui.time_index);
+        int storageIndex = XMLPrefsManager.get(int.class, XMLPrefsManager.Ui.storage_index);
+
+        final int RAM = 10, DEVICE = 11, TIME = 12, BATTERY = 13, STORAGE = 14;
+        Sequence s = new Sequence(new int[] {ramIndex, deviceIndex, batteryIndex, timeIndex, storageIndex}, new Integer[] {RAM, DEVICE, BATTERY, TIME, STORAGE});
+
+        for(int count = 0; count < s.size(); count++) {
+            int i = (int) s.get(count);
+
+            switch (i) {
+                case RAM:
+                    ram = ts[count];
+                    break;
+                case DEVICE:
+                    device = ts[count];
+                    break;
+                case BATTERY:
+                    battery = ts[count];
+                    break;
+                case STORAGE:
+                    storage = ts[count];
+                    break;
+                case TIME:
+                    time = ts[count];
+                    break;
+            }
+        }
 
         boolean showRam = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.show_ram);
         if (showRam) {
@@ -403,17 +607,37 @@ public class UIManager implements OnTouchListener {
             memory = new ActivityManager.MemoryInfo();
             activityManager = (ActivityManager) context.getSystemService(Activity.ACTIVITY_SERVICE);
 
-            ram.postDelayed(ramRunnable, RAM_DELAY);
+            ram.post(ramRunnable);
         } else {
             ram.setVisibility(View.GONE);
             ram = null;
         }
 
+        boolean showStorage = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.show_storage_info);
+        if(showStorage) {
+            storage.setTextColor(skinManager.storageColor);
+            storage.setTextSize(skinManager.getTextSize());
+            storage.setTypeface(skinManager.systemFont ? Typeface.DEFAULT : lucidaConsole);
+
+            storage.post(storageRunnable);
+        } else {
+            storage.setVisibility(View.GONE);
+        }
+
         boolean showDevice = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.show_device_name);
         if (showDevice) {
-            String deviceName = skinManager.deviceName;
 
-            device.setText(deviceName);
+            Pattern USERNAME = Pattern.compile("%u", Pattern.CASE_INSENSITIVE);
+            Pattern DV = Pattern.compile("%d", Pattern.CASE_INSENSITIVE);
+            Pattern NEWLINE = Pattern.compile("%n", Pattern.CASE_INSENSITIVE);
+
+            String deviceFormat = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.device_format);
+
+            deviceFormat = USERNAME.matcher(deviceFormat).replaceAll(skinManager.username);
+            deviceFormat = DV.matcher(deviceFormat).replaceAll(skinManager.deviceName);
+            deviceFormat = NEWLINE.matcher(deviceFormat).replaceAll(Tuils.NEWLINE);
+
+            device.setText(deviceFormat);
             device.setTextColor(skinManager.deviceColor);
             device.setTextSize(skinManager.getTextSize());
             device.setTypeface(skinManager.systemFont ? Typeface.DEFAULT : lucidaConsole);
@@ -423,7 +647,7 @@ public class UIManager implements OnTouchListener {
 
         boolean showTime = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.show_time);
         if(showTime) {
-            format = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.time_format);
+            timeFormat = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.time_format);
 
             time.setTextColor(skinManager.time_color);
             time.setTextSize(skinManager.getTextSize());
@@ -436,6 +660,20 @@ public class UIManager implements OnTouchListener {
 
         boolean showBattery = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.show_battery);
         if(showBattery) {
+            mediumPercentage = XMLPrefsManager.get(int.class, XMLPrefsManager.Behavior.battery_medium);
+            lowPercentage = XMLPrefsManager.get(int.class, XMLPrefsManager.Behavior.battery_low);
+
+//            batteryCharging = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.battery_charging_animation);
+//            if(batteryCharging) {
+//                IntentFilter filter = new IntentFilter();
+//                filter.addAction(Intent.ACTION_POWER_CONNECTED);
+//                filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
+//
+//                LocalBroadcastManager.getInstance(context).registerReceiver(new PowerConnectionReceiver(), filter);
+//            }
+
+            if(mediumPercentage < lowPercentage) skinManager.manyColorsBattery = false;
+
             battery.setTextSize(skinManager.getTextSize());
             battery.setTypeface(skinManager.systemFont ? Typeface.DEFAULT : lucidaConsole);
 
@@ -468,7 +706,7 @@ public class UIManager implements OnTouchListener {
         }
 
 //        toolbar
-        boolean showToolbar = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Toolbar.enabled);
+        boolean showToolbar = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Toolbar.show_toolbar);
         ImageButton backView = null;
         ImageButton nextView = null;
         ImageButton deleteView = null;
@@ -584,12 +822,8 @@ public class UIManager implements OnTouchListener {
         mTerminalAdapter.setDefaultHint();
     }
 
-    public void setOutput(String string) {
-        mTerminalAdapter.setOutput(string);
-    }
-
-    public void setOutput(String s, int color, boolean fromUser) {
-        mTerminalAdapter.setOutput(s, color);
+    public void setOutput(CharSequence s, int category) {
+        mTerminalAdapter.setOutput(s, category);
     }
 
     public void disableSuggestions() {
@@ -610,11 +844,6 @@ public class UIManager implements OnTouchListener {
         mTerminalAdapter.onBackPressed();
     }
 
-    //    update ram
-    public void updateRamDetails() {
-        ram.setText("free RAM: " + Tuils.ramDetails(activityManager, memory));
-    }
-
     public void focusTerminal() {
         mTerminalAdapter.requestInputFocus();
     }
@@ -721,5 +950,20 @@ public class UIManager implements OnTouchListener {
     public interface OnNewInputListener {
         void onNewInput(String input);
     }
+
+//    public class PowerConnectionReceiver extends BroadcastReceiver {
+//        @Override
+//        public void onReceive(Context context, Intent intent) {
+//            int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+//            boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;
+//
+//            if(isCharging) {
+//                battery.postDelayed(batteryChargingRunnable, BATTERY_CHARGING_DELAY);
+//            } else {
+//                battery.removeCallbacks(batteryChargingRunnable);
+//            }
+//        }
+//    }
+
 }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandAbstraction.java b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandAbstraction.java
index f8dfa00..6474c0c 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandAbstraction.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandAbstraction.java
@@ -20,6 +20,8 @@ public interface CommandAbstraction {
     int COLOR = 21;
     int CONFIG_FILE = 22;
     int CONFIG_ENTRY = 23;
+    int INT = 24;
+    int REGEX = 25;
 
     String exec(ExecutePack pack) throws Exception;
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandTuils.java b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandTuils.java
index fc9b31f..1ea6352 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/CommandTuils.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/CommandTuils.java
@@ -169,6 +169,8 @@ public class CommandTuils {
             return configEntry(input);
         } else if(type == CommandAbstraction.CONFIG_FILE) {
             return configFile(input);
+        } else if(type == CommandAbstraction.INT) {
+            return integer(input);
         }
 
         return null;
@@ -369,7 +371,6 @@ public class CommandTuils {
 
     private static ArgInfo configEntry(String input) {
         int index = input.indexOf(Tuils.SPACE);
-        if(index == -1) return new ArgInfo(input, null, true, 1);
 
         if(xmlPrefsEntrys == null) {
             xmlPrefsEntrys = new ArrayList<>();
@@ -380,7 +381,7 @@ public class CommandTuils {
             for(XMLPrefsManager.XMLPrefsSave save : NotificationManager.Options.values()) xmlPrefsEntrys.add(save);
         }
 
-        String candidate = input.substring(0,index);
+        String candidate = index == -1 ? input : input.substring(0,index);
         for(XMLPrefsManager.XMLPrefsSave xs : xmlPrefsEntrys) {
             if(xs.is(candidate)) return new ArgInfo(xs, input.substring(index + 1,input.length()), true, 1);
         }
@@ -402,6 +403,23 @@ public class CommandTuils {
         return new ArgInfo(null, input, false, 0);
     }
 
+    private static ArgInfo integer(String input) {
+        int n;
+        String s;
+
+        int index = input.indexOf(Tuils.SPACE);
+        if(index == -1) s = input;
+        else s = input.substring(0, index);
+
+        try {
+            n = Integer.parseInt(s);
+        } catch (NumberFormatException e) {
+            return new ArgInfo(null, input, false, 0);
+        }
+
+        return new ArgInfo(n, index == -1 ? null : input.substring(index + 1), true, 1);
+    }
+
     public static boolean isSuRequest(String input) {
         return input.equals("su");
     }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/community.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/community.java
new file mode 100644
index 0000000..23fd4c4
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/community.java
@@ -0,0 +1,54 @@
+package ohi.andre.consolelauncher.commands.main.raw;
+
+import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.commands.CommandAbstraction;
+import ohi.andre.consolelauncher.commands.ExecutePack;
+import ohi.andre.consolelauncher.tuils.Tuils;
+
+/**
+ * Created by francescoandreuzzi on 17/07/2017.
+ */
+
+public class community implements CommandAbstraction {
+
+    @Override
+    public String exec(ExecutePack pack) throws Exception {
+        pack.context.startActivity(Tuils.webPage("https://plus.google.com/communities/103936578623101446195"));
+        return null;
+    }
+
+    @Override
+    public int minArgs() {
+        return 0;
+    }
+
+    @Override
+    public int maxArgs() {
+        return 0;
+    }
+
+    @Override
+    public int[] argType() {
+        return new int[0];
+    }
+
+    @Override
+    public int priority() {
+        return 3;
+    }
+
+    @Override
+    public int helpRes() {
+        return R.string.help_community;
+    }
+
+    @Override
+    public String onArgNotFound(ExecutePack pack, int indexNotFound) {
+        return null;
+    }
+
+    @Override
+    public String onNotArgEnough(ExecutePack pack, int nArgs) {
+        return null;
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/config.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/config.java
index 412930f..d17e6a6 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/config.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/config.java
@@ -1,9 +1,6 @@
 package ohi.andre.consolelauncher.commands.main.raw;
 
-import android.util.Log;
-
 import java.io.File;
-import java.util.Arrays;
 
 import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
@@ -45,6 +42,18 @@ public class config extends ParamCommand {
                 pack.context.startActivity(Tuils.openFile(file));
                 return null;
             }
+        },
+        get {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.CONFIG_ENTRY};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                XMLPrefsManager.XMLPrefsSave save = pack.get(XMLPrefsManager.XMLPrefsSave.class, 1);
+                return XMLPrefsManager.get(String.class, save);
+            }
         };
 
         static Param get(String p) {
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/notifications.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/notifications.java
index 89bf19f..a9058c6 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/notifications.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/notifications.java
@@ -1,13 +1,15 @@
 package ohi.andre.consolelauncher.commands.main.raw;
 
+import android.content.Intent;
+import android.os.Build;
+import android.provider.Settings;
+
 import java.io.File;
 
 import ohi.andre.consolelauncher.R;
-import ohi.andre.consolelauncher.commands.Command;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
 import ohi.andre.consolelauncher.commands.main.MainPack;
-import ohi.andre.consolelauncher.commands.main.Param;
 import ohi.andre.consolelauncher.commands.specific.ParamCommand;
 import ohi.andre.consolelauncher.managers.notifications.NotificationManager;
 import ohi.andre.consolelauncher.tuils.Tuils;
@@ -59,28 +61,43 @@ public class notifications extends ParamCommand {
                 return new int[] {CommandAbstraction.COLOR, CommandAbstraction.VISIBLE_PACKAGE};
             }
         },
-        title_regex {
+        title_filter {
             @Override
             public String exec(ExecutePack pack) {
-                NotificationManager.excludeRegex(pack.get(String.class, 1), "title");
+                int id = pack.get(int.class, 1);
+                NotificationManager.excludeRegex(pack.get(String.class, 2), "title", id);
                 return null;
             }
 
             @Override
             public int[] args() {
-                return new int[] {CommandAbstraction.PLAIN_TEXT};
+                return new int[] {CommandAbstraction.INT, CommandAbstraction.PLAIN_TEXT};
             }
         },
-        text_regex {
+        text_filer {
             @Override
             public String exec(ExecutePack pack) {
-                NotificationManager.excludeRegex(pack.get(String.class, 1), "text");
+                int id = pack.get(int.class, 1);
+                NotificationManager.excludeRegex(pack.get(String.class, 2), "text", id);
                 return null;
             }
 
             @Override
             public int[] args() {
-                return new int[] {CommandAbstraction.PLAIN_TEXT};
+                return new int[] {CommandAbstraction.INT, CommandAbstraction.PLAIN_TEXT};
+            }
+        },
+        apply_filter {
+            @Override
+            public int[] args() {
+                return new int[] {CommandAbstraction.INT, CommandAbstraction.VISIBLE_PACKAGE};
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                int id = pack.get(int.class, 1);
+                NotificationManager.applyFilter(id, pack.get(String.class, 2));
+                return null;
             }
         },
         file {
@@ -94,6 +111,18 @@ public class notifications extends ParamCommand {
                 pack.context.startActivity(Tuils.openFile(new File(Tuils.getFolder(), NotificationManager.PATH)));
                 return null;
             }
+        },
+        access {
+            @Override
+            public int[] args() {
+                return new int[0];
+            }
+
+            @Override
+            public String exec(ExecutePack pack) {
+                pack.context.startActivity(new Intent(Build.VERSION.SDK_INT >= 22 ? Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS : "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));
+                return null;
+            }
         };
 
         static Param get(String p) {
@@ -139,7 +168,7 @@ public class notifications extends ParamCommand {
 
     @Override
     public int minArgs() {
-        return 0;
+        return 1;
     }
 
     @Override
@@ -159,6 +188,10 @@ public class notifications extends ParamCommand {
 
     @Override
     public String onArgNotFound(ExecutePack pack, int index) {
+        String arg = pack.get(String.class, 0).toLowerCase();
+        if(index == 1 && (arg.equals(Param.title_filter.label()) || arg.equals(Param.text_filer.label()) || arg.equals(Param.apply_filter.label()))) {
+            return ((MainPack) pack).context.getString(R.string.invalid_integer);
+        }
         return ((MainPack) pack).context.getString(R.string.output_appnotfound);
     }
 
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/restart.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/restart.java
index 5d41c71..d99b9bf 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/restart.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/restart.java
@@ -11,7 +11,7 @@ public class restart implements CommandAbstraction {
     public String exec(ExecutePack pack) {
         MainPack info = (MainPack) pack;
         info.reloadable.reload();
-        return "";
+        return pack.context.getString(R.string.restarting);
     }
 
     @Override
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/tutorial.java b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/tutorial.java
new file mode 100644
index 0000000..68bfa4e
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/main/raw/tutorial.java
@@ -0,0 +1,59 @@
+package ohi.andre.consolelauncher.commands.main.raw;
+
+import android.content.Intent;
+
+import ohi.andre.consolelauncher.R;
+import ohi.andre.consolelauncher.commands.CommandAbstraction;
+import ohi.andre.consolelauncher.commands.ExecutePack;
+import ohi.andre.consolelauncher.tuils.Tuils;
+
+/**
+ * Created by francescoandreuzzi on 10/07/2017.
+ */
+
+public class tutorial implements CommandAbstraction {
+
+    final String url = "https://github.com/Andre1299/TUI-ConsoleLauncher/wiki";
+
+    @Override
+    public String exec(ExecutePack pack) throws Exception {
+        Intent intent = Tuils.webPage(url);
+        if(intent != null) pack.context.startActivity(intent);
+        return null;
+    }
+
+    @Override
+    public int minArgs() {
+        return 0;
+    }
+
+    @Override
+    public int maxArgs() {
+        return 0;
+    }
+
+    @Override
+    public int[] argType() {
+        return new int[0];
+    }
+
+    @Override
+    public int priority() {
+        return 4;
+    }
+
+    @Override
+    public int helpRes() {
+        return R.string.help_tutorial;
+    }
+
+    @Override
+    public String onArgNotFound(ExecutePack pack, int indexNotFound) {
+        return null;
+    }
+
+    @Override
+    public String onNotArgEnough(ExecutePack pack, int nArgs) {
+        return null;
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/specific/ParamCommand.java b/app/src/main/java/ohi/andre/consolelauncher/commands/specific/ParamCommand.java
index 328c89c..c28e051 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/specific/ParamCommand.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/specific/ParamCommand.java
@@ -1,7 +1,5 @@
 package ohi.andre.consolelauncher.commands.specific;
 
-import android.util.Log;
-
 import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.commands.CommandAbstraction;
 import ohi.andre.consolelauncher.commands.ExecutePack;
diff --git a/app/src/main/java/ohi/andre/consolelauncher/commands/tuixt/TuixtActivity.java b/app/src/main/java/ohi/andre/consolelauncher/commands/tuixt/TuixtActivity.java
index 876722f..824fdf6 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/commands/tuixt/TuixtActivity.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/commands/tuixt/TuixtActivity.java
@@ -24,14 +24,12 @@ import android.widget.TextView;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
-import java.io.IOException;
 
 import ohi.andre.consolelauncher.R;
 import ohi.andre.consolelauncher.commands.Command;
 import ohi.andre.consolelauncher.commands.CommandGroup;
 import ohi.andre.consolelauncher.commands.CommandTuils;
 import ohi.andre.consolelauncher.managers.FileManager;
-import ohi.andre.consolelauncher.managers.XMLPrefsManager;
 import ohi.andre.consolelauncher.managers.SkinManager;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
@@ -62,8 +60,6 @@ public class TuixtActivity extends Activity {
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        Log.e("andre", "0");
-
         final Typeface lucidaConsole = Typeface.createFromAsset(getAssets(), "lucida_console.ttf");
         final LinearLayout rootView = new LinearLayout(this);
 
@@ -76,7 +72,6 @@ public class TuixtActivity extends Activity {
             path = file.getAbsolutePath();
         }
 
-        Log.e("andre", "1");
         final File file = new File(path);
 
         CommandGroup group = new CommandGroup(this, "ohi.andre.consolelauncher.commands.tuixt.raw");
@@ -91,8 +86,6 @@ public class TuixtActivity extends Activity {
             }
         }
 
-        Log.e("andre", "2");
-
         if (!skinManager.useSystemWp) {
             rootView.setBackgroundColor(skinManager.bgColor);
         } else {
@@ -112,8 +105,6 @@ public class TuixtActivity extends Activity {
 
         TextView prefixView = (TextView) inputOutputView.findViewById(R.id.prefix_view);
 
-        Log.e("andre", "3");
-
         ImageButton submitView = (ImageButton) inputOutputView.findViewById(R.id.submit_tv);
         boolean showSubmit = skinManager.showSubmit;
         if (!showSubmit) {
@@ -121,19 +112,13 @@ public class TuixtActivity extends Activity {
             submitView = null;
         }
 
-        String prefix;
-        if(skinManager.linuxAppearence) {
-            prefix = "$ ";
-        } else {
-            prefix = ">>";
-        }
+        String prefix = skinManager.prefix;
+
         prefixView.setTypeface(skinManager.systemFont ? Typeface.DEFAULT : lucidaConsole);
         prefixView.setTextColor(skinManager.inputColor);
         prefixView.setTextSize(skinManager.getTextSize());
         prefixView.setText(prefix);
 
-        Log.e("andre", "4");
-
         if (submitView != null) {
             submitView.setColorFilter(skinManager.inputColor);
             submitView.setOnClickListener(new View.OnClickListener() {
@@ -159,8 +144,6 @@ public class TuixtActivity extends Activity {
             }
         });
 
-        Log.e("andre", "5");
-
         outputView.setTypeface(skinManager.systemFont ? Typeface.DEFAULT : lucidaConsole);
         outputView.setTextSize(skinManager.getTextSize());
         outputView.setTextColor(skinManager.outputColor);
@@ -198,8 +181,6 @@ public class TuixtActivity extends Activity {
 
         setContentView(rootView);
 
-        Log.e("andre", "6");
-
 //
 //
 //        end setup part, now start
@@ -251,8 +232,6 @@ public class TuixtActivity extends Activity {
             inputView.setText("help");
             inputView.setSelection(inputView.getText().length());
         }
-
-        Log.e("andre", "7");
     }
 
     @Override
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java
index 41220a3..4ddea52 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/AppsManager.java
@@ -1,7 +1,6 @@
 package ohi.andre.consolelauncher.managers;
 
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -31,6 +30,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -61,7 +61,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
     private File folder;
 
     private AppsHolder appsHolder;
-    private List<AppInfo> hiddenApps;
+    private List<LaunchInfo> hiddenApps;
 
     private Outputable outputable;
 
@@ -121,6 +121,16 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         public boolean is(String s) {
             return name().equals(s);
         }
+
+        @Override
+        public String hasReplaced() {
+            return null;
+        }
+    }
+
+    @Override
+    public String[] deleted() {
+        return new String[0];
     }
 
     @Override
@@ -171,12 +181,18 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
     }
 
     public void fill() {
-        Map<String, AppInfo> map = createAppMap(context.getPackageManager());
-        List<AppInfo> shownApps = new ArrayList<>();
+        Map<String, LaunchInfo> map = createAppMap(context.getPackageManager());
+        List<LaunchInfo> shownApps = new ArrayList<>();
         hiddenApps = new ArrayList<>();
 
         XMLPrefsManager.XMLPrefsList values = new XMLPrefsManager.XMLPrefsList();
 
+        Map<String, XMLPrefsManager.XMLPrefsSave> replacedValues = new HashMap<>();
+        for(XMLPrefsManager.XMLPrefsSave s : Options.values()) {
+            String r = s.hasReplaced();
+            if(r != null) replacedValues.put(r, s);
+        }
+
         try {
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
             DocumentBuilder builder = factory.newDocumentBuilder();
@@ -217,7 +233,17 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                             break;
                         }
                     }
-                } else {
+                } else if(replacedValues.containsKey(nn)) {
+                    XMLPrefsManager.XMLPrefsSave s = replacedValues.remove(nn);
+
+                    Element e = (Element) node;
+                    String oldValue = e.hasAttribute(VALUE_ATTRIBUTE) ? e.getAttribute(VALUE_ATTRIBUTE) : null;
+                    root.removeChild(e);
+
+                    replacedValues.put(oldValue, s);
+                }
+//                todo support delete
+                else {
                     if(node.getNodeType() == Node.ELEMENT_NODE) {
                         Element e = (Element) node;
 
@@ -230,12 +256,19 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             }
 
             if(enums.size() > 0) {
+                Set<Map.Entry<String, XMLPrefsManager.XMLPrefsSave>> es = replacedValues.entrySet();
                 for(XMLPrefsManager.XMLPrefsSave s : enums) {
+                    String value = null;
+                    for(Map.Entry<String, XMLPrefsManager.XMLPrefsSave> e : es) {
+                        if(e.getValue().equals(s)) value = e.getKey();
+                    }
+                    if(value == null) value = s.defaultValue();
+
                     Element em = d.createElement(s.label());
-                    em.setAttribute(VALUE_ATTRIBUTE, s.defaultValue());
+                    em.setAttribute(VALUE_ATTRIBUTE, value);
                     root.appendChild(em);
 
-                    values.add(s.label(), s.defaultValue());
+                    values.add(s.label(), value);
                 }
                 writeTo(d, file);
             }
@@ -243,13 +276,13 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
 
         for(Map.Entry<String, ?> entry : this.preferences.getAll().entrySet()) {
             if (entry.getValue() instanceof Integer) {
-                AppInfo info = map.get(entry.getKey());
+                LaunchInfo info = map.get(entry.getKey());
                 if(info != null) info.launchedTimes = (Integer) entry.getValue();
             }
         }
 
-        for (Map.Entry<String, AppInfo> stringAppInfoEntry : map.entrySet()) {
-            AppInfo app = stringAppInfoEntry.getValue();
+        for (Map.Entry<String, LaunchInfo> stringLaunchInfoEntry : map.entrySet()) {
+            LaunchInfo app = stringLaunchInfoEntry.getValue();
             shownApps.add(app);
         }
 
@@ -257,44 +290,31 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         AppUtils.checkEquality(hiddenApps);
     }
 
-    private Map<String, AppInfo> createAppMap(PackageManager mgr) {
-        Map<String, AppInfo> map = new HashMap<>();
-
-//        Intent i = new Intent(Intent.ACTION_MAIN, null);
-//        i.addCategory(Intent.CATEGORY_LAUNCHER);
-//        List<ResolveInfo> infos = mgr.queryIntentActivities(i, 0);
-//
-//        for (ResolveInfo info : infos) {
-//            AppInfo app = new AppInfo(info.activityInfo.packageName, info.loadLabel(mgr).toString());
-//            map.put(info.activityInfo.packageName, app);
-//        }
-//
-//        return map;
-
-        for(ApplicationInfo info : mgr.getInstalledApplications(0)){
-            Intent intent = new Intent();
-            intent.addCategory(Intent.CATEGORY_LAUNCHER);
-            intent.setAction(Intent.ACTION_MAIN);
-            intent.setPackage(info.packageName);
-            List<ResolveInfo> list = mgr.queryIntentActivities(intent, 0);
-
-            for(ResolveInfo rInfo:list) {
-                ActivityInfo activity = rInfo.activityInfo;
-
-                Intent i = new Intent();
-                i.addCategory(Intent.CATEGORY_LAUNCHER);
-                i.setAction(Intent.ACTION_MAIN);
-                i.setPackage(activity.packageName);
-                i.setComponent(new ComponentName(activity.packageName, activity.name));
-                ResolveInfo in = mgr.resolveActivity(i, 0);
+    private Map<String, LaunchInfo> createAppMap(PackageManager mgr) {
+        Map<String, LaunchInfo> map = new HashMap<>();
 
-                ActivityInfo aInfo = in.activityInfo;
+        Intent i = new Intent(Intent.ACTION_MAIN, null);
+        i.addCategory(Intent.CATEGORY_LAUNCHER);
+        List<ResolveInfo> infos = mgr.queryIntentActivities(i, 0);
 
-                AppInfo app = new AppInfo(aInfo.packageName, aInfo.loadLabel(mgr).toString());
-                map.put(aInfo.packageName, app);
-            }
+        for (ResolveInfo info : infos) {
+            LaunchInfo app = new LaunchInfo(info.activityInfo.packageName, info.loadLabel(mgr).toString());
+            map.put(info.activityInfo.packageName, app);
         }
 
+//        Intent dialerIntent = new Intent(Intent.ACTION_DIAL);
+//        ComponentName dialer = dialerIntent.resolveActivity(mgr);
+//
+//        Intent contactsIntent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
+//        ComponentName contacts = contactsIntent.resolveActivity(mgr);
+//
+//        if(dialer != null && contacts != null && dialer.getPackageName().equals(contacts.getPackageName())) {
+//            map.remove(dialer.getPackageName());
+//
+//            map.put(dialer.getPackageName() + ".1", new LaunchInfo(dialer.getPackageName(), dialer.getClassName(), "Dialer"));
+//            map.put(contacts.getPackageName() + ".2", new LaunchInfo(contacts.getPackageName(), contacts.getClassName(), "Contacts"));
+//        }
+
         return map;
     }
 
@@ -302,74 +322,44 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         try {
             PackageManager manager = context.getPackageManager();
             ApplicationInfo info = manager.getApplicationInfo(packageName, 0);
-            AppInfo app = new AppInfo(packageName, info.loadLabel(manager).toString(), 0);
+            LaunchInfo app = new LaunchInfo(packageName, info.loadLabel(manager).toString(), 0);
             appsHolder.add(app);
             outputable.onOutput(context.getString(R.string.app_installed) + Tuils.SPACE + packageName);
         } catch (NameNotFoundException e) {}
     }
 
     private void remove(String packageName) {
-        AppInfo info = AppUtils.findAppInfo(packageName, appsHolder.getApps());
+        LaunchInfo info = AppUtils.findLaunchInfo(packageName, appsHolder.getApps());
         if(info != null) {
             appsHolder.remove(info);
             appsHolder.update(true);
         }
     }
 
-//    this looks EVERYWHERE!
-//    public String findPackage(String name) {
-//        List<AppInfo> apps = appsHolder.getApps();
-//        if(apps != null) {
-//            apps.addAll(hiddenApps);
-//            return findPackage(apps, null, name);
-//        }
-//        return null;
-//    }
-
     public String findPackage(String name, int type) {
-        List<AppInfo> appList;
-        List<String> labelList;
+        List<LaunchInfo> appList;
         if(type == SHOWN_APPS) {
             appList = appsHolder.getApps();
-            labelList = appsHolder.getAppLabels();
         } else {
             appList = hiddenApps;
-            labelList = AppUtils.labelList(appList);
         }
 
-        return findPackage(appList, labelList, name);
+        return findPackage(appList, name);
     }
 
-    public String findPackage(List<AppInfo> appList, List<String> labels, String name) {
+    public String findPackage(List<LaunchInfo> appList, String name) {
         name = Compare.removeSpaces(name);
-//        if(labels == null) {
-//            labels = AppUtils.labelList(appList);
-//        }
-
-//        if(useCompareString) {
-//            String label = Compare.similarString(labels, name, MIN_RATE, USE_SCROLL_COMPARE);
-//            if (label == null) {
-//                return null;
-//            }
-//
-//            for(AppInfo info : appList) {
-//                if (info.publicLabel.equals(name)) {
-//                    return info.packageName;
-//                }
-//            }
-//        } else {
-            for(AppInfo info : appList) {
-                if(name.equalsIgnoreCase(Compare.removeSpaces(Compare.removeSpaces(info.publicLabel)))) {
-                    return info.packageName;
-                }
+        for(LaunchInfo info : appList) {
+            if(name.equalsIgnoreCase(Compare.removeSpaces(info.publicLabel))) {
+                return info.packageName;
             }
-//        }
+        }
 
         return null;
     }
 
     public Intent getIntent(String packageName) {
-        AppInfo info = AppUtils.findAppInfo(packageName, appsHolder.getApps());
+        LaunchInfo info = AppUtils.findLaunchInfo(packageName, appsHolder.getApps());
         if(info == null) {
             return null;
         }
@@ -384,11 +374,25 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             editor.commit();
         }
 
-        return context.getPackageManager().getLaunchIntentForPackage(packageName);
+//        if(info.activityName == null)
+            return context.getPackageManager().getLaunchIntentForPackage(packageName);
+//        else {
+//            Intent i = new Intent();
+//            i.setClassName(info.packageName, info.activityName);
+//            i.putExtra("forResult", true);
+//            return i;
+//        }
+    }
+
+    public String getAppName(String packageName) {
+        for(LaunchInfo info : appsHolder.getApps()) {
+            if(info.packageName.equals(packageName)) return info.publicLabel;
+        }
+        return "null";
     }
 
     public String hideApp(String packageName) {
-        AppInfo info = AppUtils.findAppInfo(packageName, appsHolder.getApps());
+        LaunchInfo info = AppUtils.findLaunchInfo(packageName, appsHolder.getApps());
         if(info == null) {
             return null;
         }
@@ -404,7 +408,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
     }
 
     public String unhideApp(String packageName) {
-        AppInfo info = AppUtils.findAppInfo(packageName, hiddenApps);
+        LaunchInfo info = AppUtils.findLaunchInfo(packageName, hiddenApps);
         if(info == null) {
             return null;
         }
@@ -444,31 +448,37 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
         unregisterReceiver(context);
     }
 
-    public static class AppInfo {
+    public static class LaunchInfo {
 
         public String packageName;
+        public String activityName;
         public String publicLabel;
         public int launchedTimes;
 
-        public AppInfo(String packageName, String publicLabel, int launchedTimes) {
+        public LaunchInfo(String packageName, String publicLabel, int launchedTimes) {
             this.packageName = packageName;
             this.publicLabel = publicLabel;
             this.launchedTimes = launchedTimes;
         }
 
-        public AppInfo(String packageName, String publicLabel) {
+        public LaunchInfo(String packageName, String publicLabel) {
             this.packageName = packageName;
             this.publicLabel = publicLabel;
         }
 
+        public LaunchInfo(String packageName, String activityName, String publicLabel) {
+            this(packageName, publicLabel);
+            this.activityName = activityName;
+        }
+
         @Override
         public boolean equals(Object o) {
             if(o == null) {
                 return false;
             }
 
-            if(o instanceof AppInfo) {
-                AppInfo i = (AppInfo) o;
+            if(o instanceof LaunchInfo) {
+                LaunchInfo i = (LaunchInfo) o;
                 return (this.packageName == null && i.packageName == null) || (this.packageName != null && i.packageName != null && this.packageName.equals(i.packageName));
             } else if(o instanceof String) return this.packageName != null && this.packageName.equals(o);
             return false;
@@ -489,7 +499,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
 
         final int MOST_USED = 10, NULL = 11, USER_DEFINIED = 12;
 
-        private List<AppInfo> infos;
+        private List<LaunchInfo> infos;
         private List<String> appLabels;
         private XMLPrefsManager.XMLPrefsList values;
 
@@ -509,7 +519,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                     if(vl.equals(Options.NULL)) continue;
                     if(vl.equals(Options.MOST_USED)) suggested.add(new SuggestedApp(MOST_USED));
                     else {
-                        AppInfo info = AppUtils.findAppInfo(vl, infos);
+                        LaunchInfo info = AppUtils.findLaunchInfo(vl, infos);
                         if(info == null) continue;
                         suggested.add(new SuggestedApp(info, USER_DEFINIED));
                     }
@@ -539,15 +549,15 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                 return suggested.get(index);
             }
 
-            public void set(int index, AppInfo info) {
+            public void set(int index, LaunchInfo info) {
                 suggested.get(index).change(info);
             }
 
-            public int indexOf(AppInfo info) {
+            public int indexOf(LaunchInfo info) {
                 return suggested.indexOf(info);
             }
 
-            public void attemptInsertSuggestion(AppInfo info) {
+            public void attemptInsertSuggestion(LaunchInfo info) {
 //                Log.e("andre", "attempt: " + info.toString());
 
                 if (info.launchedTimes == 0 || lastWriteable == -1) {
@@ -573,7 +583,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
 //                                Log.e("andre", "before it was: " + s.toString());
 //                                Log.e("andre", suggested.toString());
 
-                                AppInfo before = s.app;
+                                LaunchInfo before = s.app;
                                 s.change(info);
 
 //                                Log.e("andre", suggested.toString());
@@ -596,7 +606,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
 //                Log.e("andre", suggested.toString());
             }
 
-//            public void updateSuggestion(AppInfo info) {
+//            public void updateSuggestion(LaunchInfo info) {
 //                int index = indexOf(info);
 //
 //                if(index == -1) {
@@ -622,7 +632,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
 //            }
 
             public List<String> labels() {
-                List<AppInfo> list = new ArrayList<>();
+                List<LaunchInfo> list = new ArrayList<>();
                 for(int count = 0; count < suggested.size(); count++) {
                     SuggestedApp app = suggested.get(count);
                     if(app.type != NULL && app.app != null) list.add(app.app);
@@ -651,18 +661,18 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
 
             private class SuggestedApp implements Comparable {
                 int type;
-                AppInfo app;
+                LaunchInfo app;
 
                 public SuggestedApp(int type) {
                     this(null, type);
                 }
 
-                public SuggestedApp(AppInfo info, int type) {
+                public SuggestedApp(LaunchInfo info, int type) {
                     this.app = info;
                     this.type = type;
                 }
 
-                public SuggestedApp change(AppInfo info) {
+                public SuggestedApp change(LaunchInfo info) {
                     this.app = info;
                     return this;
                 }
@@ -675,7 +685,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                         } catch (NullPointerException e) {
                             return false;
                         }
-                    } else if(o instanceof AppInfo) {
+                    } else if(o instanceof LaunchInfo) {
                         if(app == null) return false;
                         return app.equals(o);
                     }
@@ -717,27 +727,27 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             }
         }
 
-        Comparator<AppInfo> mostUsedComparator = new Comparator<AppInfo>() {
+        Comparator<LaunchInfo> mostUsedComparator = new Comparator<LaunchInfo>() {
             @Override
-            public int compare(AppInfo lhs, AppInfo rhs) {
+            public int compare(LaunchInfo lhs, LaunchInfo rhs) {
                 return rhs.launchedTimes > lhs.launchedTimes ? -1 : rhs.launchedTimes == lhs.launchedTimes ? 0 : 1;
             }
         };
 
-        public AppsHolder(List<AppInfo> infos, XMLPrefsManager.XMLPrefsList values) {
+        public AppsHolder(List<LaunchInfo> infos, XMLPrefsManager.XMLPrefsList values) {
             this.infos = infos;
             this.values = values;
             update(true);
         }
 
-        public void add(AppInfo info) {
+        public void add(LaunchInfo info) {
             if(! infos.contains(info) ) {
                 infos.add(info);
                 update(false);
             }
         }
 
-        public void remove(AppInfo info) {
+        public void remove(LaunchInfo info) {
             infos.remove(info);
             update(true);
         }
@@ -754,12 +764,12 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
 
         private void fillSuggestions() {
             suggestedAppMgr = new SuggestedAppMgr(values);
-            for(AppInfo info : infos) {
+            for(LaunchInfo info : infos) {
                 suggestedAppMgr.attemptInsertSuggestion(info);
             }
         }
 
-        public void requestSuggestionUpdate(AppInfo info) {
+        public void requestSuggestionUpdate(LaunchInfo info) {
             suggestedAppMgr.attemptInsertSuggestion(info);
         }
 
@@ -785,7 +795,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             return appLabels;
         }
 
-        public List<AppInfo> getApps() {
+        public List<LaunchInfo> getApps() {
             return infos;
         }
 
@@ -797,16 +807,16 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
 
     public static class AppUtils {
 
-        public static void checkEquality(List<AppInfo> list) {
+        public static void checkEquality(List<LaunchInfo> list) {
 
-            for (AppInfo info : list) {
+            for (LaunchInfo info : list) {
 
                 if(info == null || info.publicLabel == null) {
                     continue;
                 }
 
                 for (int count = 0; count < list.size(); count++) {
-                    AppInfo info2 = list.get(count);
+                    LaunchInfo info2 = list.get(count);
 
                     if(info2 == null || info2.publicLabel == null) {
                         continue;
@@ -817,7 +827,7 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
                     }
 
                     if (info.publicLabel.toLowerCase().replace(Tuils.SPACE, Tuils.EMPTYSTRING).equals(info2.publicLabel.toLowerCase().replace(Tuils.SPACE, Tuils.EMPTYSTRING))) {
-                        list.set(count, new AppInfo(info2.packageName, getNewLabel(info2.publicLabel, info2.packageName), info2.launchedTimes));
+                        list.set(count, new LaunchInfo(info2.packageName, getNewLabel(info2.publicLabel, info2.packageName), info2.launchedTimes));
                     }
                 }
             }
@@ -898,8 +908,8 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             return builder.toString();
         }
 
-        protected static AppInfo findAppInfo(String packageName, List<AppInfo> infos) {
-            for(AppInfo info : infos) {
+        protected static LaunchInfo findLaunchInfo(String packageName, List<LaunchInfo> infos) {
+            for(LaunchInfo info : infos) {
                 if(info.packageName.equals(packageName)) {
                     return info;
                 }
@@ -926,24 +936,14 @@ public class AppsManager implements XMLPrefsManager.XmlPrefsElement {
             return Tuils.toPlanString(list);
         }
 
-        public static List<String> labelList(List<AppInfo> infos) {
+        public static List<String> labelList(List<LaunchInfo> infos) {
             List<String> labels = new ArrayList<>();
-            for (AppInfo info : infos) {
+            for (LaunchInfo info : infos) {
                 labels.add(info.publicLabel);
             }
             Collections.sort(labels);
             return labels;
         }
-
-        public static String[] labelList(AppInfo[] infos) {
-            String[] labels = new String[infos.length];
-            for(int count = 0; count < infos.length; count++) {
-                if(infos[count] != null) {
-                    labels[count] = infos[count].publicLabel;
-                }
-            }
-            return labels;
-        }
     }
 
 }
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/ContactManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/ContactManager.java
index b08b737..fca527a 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/ContactManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/ContactManager.java
@@ -160,6 +160,11 @@ public class ContactManager {
             phones.close();
         }
 
+        List<Contact> cp = new ArrayList<>(contacts);
+        for(int count = 0; count < cp.size(); count++) {
+            if(cp.get(count).numbers.size() == 0) contacts.remove(count--);
+        }
+
         return contacts;
     }
 
@@ -348,12 +353,21 @@ public class ContactManager {
         public String name;
         public List<String> numbers = new ArrayList<>();
 
-        public int selectedNumber;
+        private int selectedNumber;
 
         public Contact(String name, List<String> numbers, int defNumber) {
             this.name = name;
             this.numbers = numbers;
-            this.selectedNumber = defNumber;
+
+            setSelectedNumber(defNumber);
+        }
+
+        public void setSelectedNumber(int s) {
+            if(s >= numbers.size()) s = 0;
+        }
+
+        public int getSelectedNumber() {
+            return selectedNumber;
         }
 
         @Override
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/SkinManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/SkinManager.java
index c361c08..d1c65d6 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/SkinManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/SkinManager.java
@@ -25,12 +25,13 @@ public class SkinManager implements Parcelable {
     public int globalFontSize;
 
     public String deviceName;
-    public int deviceColor, inputColor, outputColor, ramColor, bgColor, overlayColor, toolbarColor, toolbarBg, enter_color, time_color, battery_color_high, battery_color_medium, battery_color_low;
+    public int deviceColor, inputColor, outputColor, ramColor, bgColor, overlayColor, toolbarColor, toolbarBg, enter_color, time_color, battery_color_high, battery_color_medium, battery_color_low,
+            storageColor;
 
     public boolean useSystemWp, showSuggestions, systemFont, inputBottom, showSubmit, manyColorsBattery;
 
-    public String username = null;
-    public boolean showUsernameAndDeviceWhenEmpty = true, showUsername = false, showDeviceInSessionInfo = false, linuxAppearence = true, showPath = true;
+    public String username = null, prefix;
+    public boolean showUsernameAndDeviceWhenEmpty = true, showUsername = false, showDeviceInSessionInfo = false, showPath = true;
 
     private int suggDefaultText, suggDefaultBg, suggAliasText, suggAliasBg, suggSongText, suggSongBg, suggContactText, suggContactBg, suggAppText, suggAppBg, suggCmdText, suggCmdBg, suggFileText, suggFileBg;
     private boolean transparentSuggestions;
@@ -59,31 +60,30 @@ public class SkinManager implements Parcelable {
         toolbarBg = XMLPrefsManager.getColor(XMLPrefsManager.Theme.toolbar_bg);
         enter_color = XMLPrefsManager.getColor(XMLPrefsManager.Theme.enter_color);
         time_color = XMLPrefsManager.getColor(XMLPrefsManager.Theme.time_color);
+        storageColor = XMLPrefsManager.getColor(XMLPrefsManager.Theme.storage_color);
         battery_color_high = XMLPrefsManager.getColor(XMLPrefsManager.Theme.battery_color_high);
         if(manyColorsBattery) {
             battery_color_medium = XMLPrefsManager.getColor(XMLPrefsManager.Theme.battery_color_medium);
             battery_color_low = XMLPrefsManager.getColor(XMLPrefsManager.Theme.battery_color_low);
         }
 
+        prefix = XMLPrefsManager.get(String.class, XMLPrefsManager.Ui.input_prefix);
+
         deviceName = XMLPrefsManager.get(String.class, XMLPrefsManager.Ui.deviceName);
         if (deviceName.length() == 0 || deviceName.equals("null")) {
             deviceName = Build.DEVICE;
         }
 
+        username = XMLPrefsManager.get(String.class, XMLPrefsManager.Ui.username);
         showUsernameAndDeviceWhenEmpty = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.show_ssninfo);
         if(showUsernameAndDeviceWhenEmpty) {
             showUsername = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.show_username_ssninfo);
-            if(showUsername) {
-                username = XMLPrefsManager.get(String.class, XMLPrefsManager.Ui.username);
-            }
 
             showDeviceInSessionInfo = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.show_devicename_ssninfo);
             showPath = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.show_path_ssninfo);
         }
 
-        linuxAppearence = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Ui.linux_like);
-
-        showSuggestions = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Suggestions.enabled);
+        showSuggestions = XMLPrefsManager.get(boolean.class, XMLPrefsManager.Suggestions.show_suggestions);
         if (showSuggestions) {
 
             suggDefaultText = XMLPrefsManager.getColor(XMLPrefsManager.Suggestions.default_text_color);
@@ -140,7 +140,6 @@ public class SkinManager implements Parcelable {
         showUsernameAndDeviceWhenEmpty = in.readByte() != 0;
         showUsername = in.readByte() != 0;
         showDeviceInSessionInfo = in.readByte() != 0;
-        linuxAppearence = in.readByte() != 0;
         showPath = in.readByte() != 0;
         suggDefaultText = in.readInt();
         suggDefaultBg = in.readInt();
@@ -157,6 +156,7 @@ public class SkinManager implements Parcelable {
         suggFileText = in.readInt();
         suggFileBg = in.readInt();
         transparentSuggestions = in.readByte() != 0;
+        prefix = in.readString();
     }
 
     public static final Creator<SkinManager> CREATOR = new Creator<SkinManager>() {
@@ -265,7 +265,6 @@ public class SkinManager implements Parcelable {
         dest.writeByte((byte) (showUsernameAndDeviceWhenEmpty ? 1 : 0));
         dest.writeByte((byte) (showUsername ? 1 : 0));
         dest.writeByte((byte) (showDeviceInSessionInfo ? 1 : 0));
-        dest.writeByte((byte) (linuxAppearence ? 1 : 0));
         dest.writeByte((byte) (showPath ? 1 : 0));
         dest.writeInt(suggDefaultText);
         dest.writeInt(suggDefaultBg);
@@ -282,5 +281,6 @@ public class SkinManager implements Parcelable {
         dest.writeInt(suggFileText);
         dest.writeInt(suggFileBg);
         dest.writeByte((byte) (transparentSuggestions ? 1 : 0));
+        dest.writeString(prefix);
     }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalMAnager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalMAnager.java
index 2070ddb..af1a523 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalMAnager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/TerminalMAnager.java
@@ -4,11 +4,14 @@ import android.content.Context;
 import android.graphics.Typeface;
 import android.os.IBinder;
 import android.text.InputType;
-import android.text.Spannable;
+import android.text.Layout;
 import android.text.SpannableString;
+import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.format.Time;
 import android.text.method.ScrollingMovementMethod;
 import android.text.style.ForegroundColorSpan;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewTreeObserver;
@@ -45,12 +48,14 @@ public class TerminalManager {
     private final int SCROLL_DELAY = 200;
     private final int CMD_LIST_SIZE = 40;
 
-    public static final int INPUT = 10;
-    public static final int OUTPUT = 11;
+    public static final int CATEGORY_INPUT = 10;
+    public static final int CATEGORY_OUTPUT = 11;
+    public static final int CATEGORY_NOTIFICATION = 12;
 
     private long lastEnter;
 
-    private CharSequence prefix;
+    private String prefix;
+    private String suPrefix;
 
     private ScrollView mScrollView;
     private TextView mTerminalView;
@@ -90,6 +95,12 @@ public class TerminalManager {
         }
     };
 
+    private String timeFormat;
+    private Time time;
+
+    private String inputFormat;
+    private String outputFormat;
+
     public TerminalManager(final TextView terminalView, EditText inputView, TextView prefixView, ImageButton submitView, final ImageButton backView, ImageButton nextView, ImageButton deleteView,
                            ImageButton pasteView, SkinManager skinManager, final Context context, MainPack mainPack) {
         if (terminalView == null || inputView == null || prefixView == null || skinManager == null)
@@ -104,15 +115,19 @@ public class TerminalManager {
         this.clearAfterCmds = XMLPrefsManager.get(int.class, XMLPrefsManager.Behavior.clear_after_cmds);
         this.maxLines = XMLPrefsManager.get(int.class, XMLPrefsManager.Behavior.max_lines);
 
-        if(skinManager.linuxAppearence) {
-            prefix = "$ ";
-        } else {
-            prefix = ">> ";
-        }
+        timeFormat = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.time_format);
+        time = new Time();
+
+        inputFormat = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.input_format);
+        outputFormat = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.output_format);
+
+        prefix = skinManager.prefix;
+        suPrefix = XMLPrefsManager.get(String.class, XMLPrefsManager.Ui.input_root_prefix);
+
         prefixView.setTypeface(skinManager.systemFont ? Typeface.DEFAULT : lucidaConsole);
         prefixView.setTextColor(this.mSkinManager.inputColor);
         prefixView.setTextSize(this.mSkinManager.getTextSize());
-        prefixView.setText(prefix);
+        prefixView.setText(prefix.endsWith(Tuils.SPACE) ? prefix : prefix + Tuils.SPACE);
 
         if (submitView != null) {
             submitView.setColorFilter(mSkinManager.enter_color);
@@ -179,7 +194,12 @@ public class TerminalManager {
             this.mTerminalView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                 @Override
                 public boolean onPreDraw() {
-                    int count = terminalView.getLayout().getLineCount() - 1;
+                    if(TerminalManager.this.mTerminalView == null) return true;
+
+                    Layout l = terminalView.getLayout();
+                    if(l == null) return true;
+
+                    int count = l.getLineCount() - 1;
 
                     if(count > maxLines) {
                         int excessive = count - maxLines;
@@ -270,9 +290,9 @@ public class TerminalManager {
 
             if(clearCmdsCount != 0 && clearAfterCmds > 0 && clearCmdsCount % clearAfterCmds == 0) clear();
 
-            for (Messager messager : messagers) if (messagesCmdsCount != 0 && messagesCmdsCount % messager.n == 0) writeToView(messager.message, OUTPUT);
+            for (Messager messager : messagers) if (messagesCmdsCount != 0 && messagesCmdsCount % messager.n == 0) writeToView(messager.message, CATEGORY_OUTPUT);
 
-            writeToView((input.startsWith("su ") ? "# " : prefix) + input, INPUT);
+            writeToView(input, CATEGORY_INPUT);
 
             if(cmdList.size() == CMD_LIST_SIZE) {
                 cmdList.remove(0);
@@ -291,27 +311,15 @@ public class TerminalManager {
         return true;
     }
 
-    public void setOutput(String output) {
-        setOutput(output, -1, OUTPUT);
-    }
-
-    public void setOutput(String output, int color) {
-        setOutput(output, color, -1);
-    }
-
-    public void setOutput(String output, int color, int type) {
-        if (output == null) return;
-
-        output = output.trim();
-        if(output.equals(Tuils.EMPTYSTRING)) return;
+    public void setOutput(CharSequence output, int type) {
+        if (output == null || output.length() == 0) return;
 
         if(output.equals(clear.CLEAR)) {
             clear();
             return;
         }
 
-        if(color == -1) writeToView(output, type);
-        else writeToView(color, output);
+        writeToView(output, type);
     }
 
     public void onBackPressed() {
@@ -343,34 +351,63 @@ public class TerminalManager {
         }
     }
 
-    private void writeToView(final String text, final int type) {
+    final String FORMAT_INPUT = "%i";
+    final String FORMAT_OUTPUT = "%o";
+    final String FORMAT_PREFIX = "%p";
+    final String FORMAT_TIME = "%t";
+    final String FORMAT_NEWLINE = "%n";
+
+    private void writeToView(final CharSequence text, final int type) {
         mTerminalView.post(new Runnable() {
             @Override
             public void run() {
-                String txt = text;
-                txt = Tuils.NEWLINE.concat(txt);
-
-                SpannableString string = getSpannable(txt, type);
-                mTerminalView.append(string);
 
+                mTerminalView.append(TextUtils.concat(Tuils.NEWLINE, getFinalText(text, type)));
                 scrollToEnd();
             }
         });
     }
+    private CharSequence getFinalText(CharSequence t, int type) {
+        time.setToNow();
+        String tm = time.format(timeFormat);
+        SpannableString st = new SpannableString(tm);
+        st.setSpan(new ForegroundColorSpan(mSkinManager.time_color), 0, tm.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        CharSequence s;
+        switch (type) {
+            case CATEGORY_INPUT:
+                t = t.toString().trim();
+
+                boolean su = t.toString().startsWith("su ");
+
+                SpannableString si = new SpannableString(inputFormat);
+                si.setSpan(new ForegroundColorSpan(mSkinManager.inputColor), 0, inputFormat.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+                s = TextUtils.replace(si,
+                        new String[] {FORMAT_INPUT, FORMAT_PREFIX, FORMAT_TIME, FORMAT_NEWLINE,
+                                FORMAT_INPUT.toUpperCase(), FORMAT_PREFIX.toUpperCase(), FORMAT_TIME.toUpperCase(), FORMAT_NEWLINE.toUpperCase()},
+                        new CharSequence[] {t, su ? suPrefix : prefix, st, Tuils.NEWLINE, t, su ? suPrefix : prefix, st, Tuils.NEWLINE});
+
+                break;
+            case CATEGORY_OUTPUT:
+                t = t.toString().trim();
+
+                SpannableString so = new SpannableString(outputFormat);
+                so.setSpan(new ForegroundColorSpan(mSkinManager.outputColor), 0, outputFormat.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+                s = TextUtils.replace(so,
+                        new String[] {FORMAT_OUTPUT, FORMAT_TIME, FORMAT_NEWLINE, FORMAT_OUTPUT.toUpperCase(), FORMAT_TIME.toUpperCase(), FORMAT_NEWLINE.toUpperCase()},
+                        new CharSequence[] {t, st, Tuils.NEWLINE, t, st, Tuils.NEWLINE});
+
+                break;
+            case CATEGORY_NOTIFICATION:
+                s = t;
+                break;
+            default:
+                return null;
+        }
 
-    private void writeToView(final int color, final String text) {
-        mTerminalView.post(new Runnable() {
-            @Override
-            public void run() {
-                String txt = text;
-                txt = Tuils.NEWLINE.concat(txt);
-
-                SpannableString string = getSpannable(color, txt);
-                mTerminalView.append(string);
-
-                scrollToEnd();
-            }
-        });
+        return s;
     }
 
     public void simulateEnter() {
@@ -381,24 +418,6 @@ public class TerminalManager {
         this.mTerminalView.setMovementMethod(new ScrollingMovementMethod());
     }
 
-    private SpannableString getSpannable(String text, int type) {
-        int color;
-        if(type == INPUT) {
-            color = mSkinManager.inputColor;
-        } else if(type == OUTPUT) {
-            color = mSkinManager.outputColor;
-        } else {
-            return null;
-        }
-        return getSpannable(color, text);
-    }
-
-    private SpannableString getSpannable(int color, String text) {
-        SpannableString spannableString = new SpannableString(text);
-        spannableString.setSpan(new ForegroundColorSpan(color), 0, spannableString.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
-        return spannableString;
-    }
-
     public String getInput() {
         return mInputView.getText().toString();
     }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/XMLPrefsManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/XMLPrefsManager.java
index 4803de3..7e8b2c7 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/XMLPrefsManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/XMLPrefsManager.java
@@ -7,12 +7,18 @@ import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.regex.Pattern;
 
 import javax.xml.parsers.DocumentBuilder;
@@ -22,6 +28,8 @@ import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
+import ohi.andre.consolelauncher.managers.notifications.NotificationManager;
+import ohi.andre.consolelauncher.tuils.SimpleMutableEntry;
 import ohi.andre.consolelauncher.tuils.Tuils;
 
 public class XMLPrefsManager {
@@ -35,6 +43,7 @@ public class XMLPrefsManager {
         String label();
         XmlPrefsElement parent();
         boolean is(String s);
+        String hasReplaced();
     }
 
     public enum Theme implements XMLPrefsSave {
@@ -87,6 +96,12 @@ public class XMLPrefsManager {
                 return "#03A9F4";
             }
         },
+        storage_color {
+            @Override
+            public String defaultValue() {
+                return "#9C27B0";
+            }
+        },
         ram_color {
             @Override
             public String defaultValue() {
@@ -132,6 +147,11 @@ public class XMLPrefsManager {
         public boolean is(String s) {
             return name().equals(s);
         }
+
+        @Override
+        public String hasReplaced() {
+            return null;
+        }
     }
 
     public enum Ui implements XMLPrefsSave {
@@ -148,12 +168,6 @@ public class XMLPrefsManager {
                 return "true";
             }
         },
-        linux_like {
-            @Override
-            public String defaultValue() {
-                return "true";
-            }
-        },
         show_path_ssninfo {
             @Override
             public String defaultValue() {
@@ -208,6 +222,12 @@ public class XMLPrefsManager {
                 return "true";
             }
         },
+        show_storage_info {
+            @Override
+            public String defaultValue() {
+                return "true";
+            }
+        },
         enable_battery_status {
             @Override
             public String defaultValue() {
@@ -243,6 +263,48 @@ public class XMLPrefsManager {
             public String defaultValue() {
                 return "false";
             }
+        },
+        device_index {
+            @Override
+            public String defaultValue() {
+                return "0";
+            }
+        },
+        ram_index {
+            @Override
+            public String defaultValue() {
+                return "1";
+            }
+        },
+        battery_index {
+            @Override
+            public String defaultValue() {
+                return "2";
+            }
+        },
+        time_index {
+            @Override
+            public String defaultValue() {
+                return "3";
+            }
+        },
+        storage_index {
+            @Override
+            public String defaultValue() {
+                return "4";
+            }
+        },
+        input_prefix {
+            @Override
+            public String defaultValue() {
+                return "$";
+            }
+        },
+        input_root_prefix {
+            @Override
+            public String defaultValue() {
+                return "#";
+            }
         };
 
         @Override
@@ -259,15 +321,25 @@ public class XMLPrefsManager {
         public boolean is(String s) {
             return name().equals(s);
         }
+
+        @Override
+        public String hasReplaced() {
+            return null;
+        }
     }
 
     public enum Toolbar implements XMLPrefsSave {
 
-        enabled {
+        show_toolbar {
             @Override
             public String defaultValue() {
                 return "true";
             }
+
+            @Override
+            public String hasReplaced() {
+                return "enabled";
+            }
         };
 
         @Override
@@ -288,11 +360,16 @@ public class XMLPrefsManager {
 
     public enum Suggestions implements XMLPrefsSave {
 
-        enabled {
+        show_suggestions {
             @Override
             public String defaultValue() {
                 return "true";
             }
+
+            @Override
+            public String hasReplaced() {
+                return "enabled";
+            }
         },
         transparent {
             @Override
@@ -399,6 +476,11 @@ public class XMLPrefsManager {
         public boolean is(String s) {
             return name().equals(s);
         }
+
+        @Override
+        public String hasReplaced() {
+            return null;
+        }
     }
 
     public enum Behavior implements XMLPrefsSave {
@@ -498,6 +580,54 @@ public class XMLPrefsManager {
             public String defaultValue() {
                 return "%m/%d/%y %H.%M";
             }
+        },
+        battery_medium {
+            @Override
+            public String defaultValue() {
+                return "50";
+            }
+        },
+        battery_low {
+            @Override
+            public String defaultValue() {
+                return "15";
+            }
+        },
+        device_format {
+            @Override
+            public String defaultValue() {
+                return "%d: %u";
+            }
+        },
+        ram_format {
+            @Override
+            public String defaultValue() {
+                return "Available RAM: %avgb GB of %totgb GB (%av%%)";
+            }
+        },
+        battery_format {
+            @Override
+            public String defaultValue() {
+                return "%v%";
+            }
+        },
+        storage_format {
+            @Override
+            public String defaultValue() {
+                return "Internal Storage: %iavmb MB of %itotmb MB (%iav%%)";
+            }
+        },
+        input_format {
+            @Override
+            public String defaultValue() {
+                return "[%t] %p %i";
+            }
+        },
+        output_format {
+            @Override
+            public String defaultValue() {
+                return "%o";
+            }
         };
 
         @Override
@@ -514,6 +644,11 @@ public class XMLPrefsManager {
         public boolean is(String s) {
             return name().equals(s);
         }
+
+        @Override
+        public String hasReplaced() {
+            return null;
+        }
     }
 
     public enum Cmd implements XMLPrefsSave {
@@ -539,16 +674,51 @@ public class XMLPrefsManager {
         public boolean is(String s) {
             return name().equals(s);
         }
+
+        @Override
+        public String hasReplaced() {
+            return null;
+        }
     }
 
     public enum XMLPrefsRoot implements XmlPrefsElement {
 
-        THEME("theme.xml", Theme.values()),
-        CMD("cmd.xml", Cmd.values()),
-        TOOLBAR("toolbar.xml", Toolbar.values()),
-        UI("ui.xml", Ui.values()),
-        BEHAVIOR("behavior.xml", Behavior.values()),
-        SUGGESTIONS("suggestions.xml", Suggestions.values());
+        THEME("theme.xml", Theme.values()) {
+            @Override
+            public String[] deleted() {
+                return new String[0];
+            }
+        },
+        CMD("cmd.xml", Cmd.values()) {
+            @Override
+            public String[] deleted() {
+                return new String[] {"time_format"};
+            }
+        },
+        TOOLBAR("toolbar.xml", Toolbar.values()) {
+            @Override
+            public String[] deleted() {
+                return new String[0];
+            }
+        },
+        UI("ui.xml", Ui.values()) {
+            @Override
+            public String[] deleted() {
+                return new String[] {"show_timestamp_before_cmd", "linux_like"};
+            }
+        },
+        BEHAVIOR("behavior.xml", Behavior.values()) {
+            @Override
+            public String[] deleted() {
+                return new String[0];
+            }
+        },
+        SUGGESTIONS("suggestions.xml", Suggestions.values()) {
+            @Override
+            public String[] deleted() {
+                return new String[0];
+            }
+        };
 
 //        notifications
 //        apps
@@ -581,6 +751,7 @@ public class XMLPrefsManager {
     public interface XmlPrefsElement {
         XMLPrefsList getValues();
         void write(XMLPrefsSave save, String value);
+        String[] deleted();
     }
 
     public static class XMLPrefsEntry {
@@ -647,6 +818,15 @@ public class XMLPrefsManager {
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         DocumentBuilder builder = factory.newDocumentBuilder();
 
+        BufferedReader oldStream = null;
+        HashMap<XMLPrefsSave, String> oldValues = null;
+
+        File old = new File(folder, "settings.txt");
+        if(old.exists()) {
+            oldStream = new BufferedReader(new FileReader(old));
+            oldValues = getOld(oldStream);
+        }
+
         for(XMLPrefsRoot element : XMLPrefsRoot.values()) {
             File file = new File(folder, element.path);
             if(!file.exists() && !file.createNewFile()) continue;
@@ -663,6 +843,14 @@ public class XMLPrefsManager {
             List<XMLPrefsSave> enums = element.enums;
             if(enums == null) continue;
 
+            Map<String, XMLPrefsManager.XMLPrefsSave> replacedValues = new HashMap<>();
+            for(XMLPrefsManager.XMLPrefsSave s : NotificationManager.Options.values()) {
+                String r = s.hasReplaced();
+                if(r != null) replacedValues.put(r, s);
+            }
+
+            String[] deleted = element.deleted();
+
             Element root = (Element) d.getElementsByTagName(element.name()).item(0);
             if(root == null) {
                 resetFile(file, element.name());
@@ -671,43 +859,69 @@ public class XMLPrefsManager {
             }
             NodeList nodes = root.getElementsByTagName("*");
 
-//            List<Node> customNodes = null;
-//            if(element.flag == FLAG_HAS_CUSTOM_TAGS || element.flag == FLAG_CUSTOM_TAGS_ONLY) customNodes = new ArrayList<>();
-
             for(int count = 0; count < nodes.getLength(); count++) {
                 Node node = nodes.item(count);
 
                 String nn = node.getNodeName();
-//                if(customNodes == null) {
                 element.values.add(nn, node.getAttributes().getNamedItem(VALUE_ATTRIBUTE).getNodeValue());
-//                } else {
-//                    if(element.flag != FLAG_CUSTOM_TAGS_ONLY && element.contains(nn)) element.values.add(nn, node.getAttributes().getNamedItem("value").getNodeValue());
-//                    else {
-//                        customNodes.add(node);
-//                        continue;
-//                    }
-//                }
 
                 for(int en = 0; en < enums.size(); en++) {
                     if(enums.get(en).label().equals(nn)) {
                         enums.remove(en);
                         break;
+                    } else if(replacedValues.containsKey(nn)) {
+                        XMLPrefsManager.XMLPrefsSave s = replacedValues.remove(nn);
+
+                        Element e = (Element) node;
+                        String oldValue = e.hasAttribute(VALUE_ATTRIBUTE) ? e.getAttribute(VALUE_ATTRIBUTE) : null;
+                        root.removeChild(e);
+
+                        replacedValues.put(oldValue, s);
+                    } else if(deleted != null) {
+                        int index = Tuils.find(nn, deleted);
+                        if(index != -1) {
+                            deleted[index] = null;
+                            Element e = (Element) node;
+                            root.removeChild(e);
+                        }
                     }
                 }
             }
 
             if(enums.size() == 0) continue;
 
+            Set<Map.Entry<String, XMLPrefsSave>> es = replacedValues.entrySet();
+
             for(XMLPrefsSave s : enums) {
+                String value = null;
+                for(Map.Entry<String, XMLPrefsManager.XMLPrefsSave> e : es) {
+                    if(e.getValue().equals(s)) value = e.getKey();
+                }
+                if(value == null) {
+
+                    if(oldValues != null) {
+                        for(Map.Entry<XMLPrefsSave, String> sm : oldValues.entrySet()) {
+                            if(sm.getKey().equals(s)) {
+                                value = sm.getValue();
+                            }
+                        }
+                    }
+
+                    if(value == null) value = s.defaultValue();
+                }
+
+
                 Element em = d.createElement(s.label());
-                em.setAttribute(VALUE_ATTRIBUTE, s.defaultValue());
+                em.setAttribute(VALUE_ATTRIBUTE, value);
                 root.appendChild(em);
 
-                element.values.add(s.label(), s.defaultValue());
+                element.values.add(s.label(), value);
             }
 
             writeTo(d, file);
         }
+
+        if(old.exists()) old.delete();
     }
 
     public static Object transform(String s, Class<?> c) {
@@ -728,7 +942,7 @@ public class XMLPrefsManager {
     static final Pattern p1 = Pattern.compile(">");
 //    static final Pattern p2 = Pattern.compile("</");
     static final Pattern p3 = Pattern.compile("\n\n");
-    static final String p1s = ">\n";
+    static final String p1s = ">" + Tuils.NEWLINE;
 //    static final String p2s = "\n</";
     static final String p3s = Tuils.NEWLINE;
 
@@ -759,6 +973,34 @@ public class XMLPrefsManager {
         } catch (Exception e) {}
     }
 
+    public static String add(File file, String rootName, String elementName, String[] attributeNames, String[] attributeValues) {
+        try {
+            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+            DocumentBuilder builder = factory.newDocumentBuilder();
+
+            Document d;
+            try {
+                d = builder.parse(file);
+            } catch (Exception e) {
+                return e.toString();
+            }
+
+            Element root = (Element) d.getElementsByTagName(rootName).item(0);
+
+            Element element = d.createElement(elementName);
+            for(int c = 0; c < attributeNames.length; c++) {
+                if(attributeValues[c] == null) continue;
+                element.setAttribute(attributeNames[c], attributeValues[c]);
+            }
+            root.appendChild(element);
+
+            writeTo(d, file);
+        } catch (Exception e) {
+            return e.toString();
+        }
+        return null;
+    }
+
     public static String set(File file, String rootName, String elementName, String[] attributeNames, String[] attributeValues) {
         String[][] values = new String[1][attributeValues.length];
         values[0] = attributeValues;
@@ -912,4 +1154,83 @@ public class XMLPrefsManager {
             return false;
         }
     }
+
+    private static HashMap<XMLPrefsSave, String> getOld(BufferedReader reader) {
+        HashMap<XMLPrefsSave, String> map = new HashMap<>();
+
+        String line;
+        try {
+            while((line = reader.readLine()) != null) {
+                String[] split = line.split("=");
+                if(split.length != 2) continue;
+
+                String name = split[0].trim();
+                String value = split[1];
+
+                XMLPrefsSave s = getCorresponding(name);
+                if(s == null) continue;
+
+                map.put(s, value);
+            }
+        } catch (IOException e) {
+            return null;
+        }
+
+        return map;
+    }
+
+    static final SimpleMutableEntry[] OLD = {
+            new SimpleMutableEntry("deviceColor", Theme.device_color),
+            new SimpleMutableEntry("inputColor", Theme.input_color),
+            new SimpleMutableEntry("outputColor", Theme.output_color),
+            new SimpleMutableEntry("backgroundColor", Theme.bg_color),
+            new SimpleMutableEntry("useSystemFont", Ui.system_font),
+            new SimpleMutableEntry("fontSize", Ui.font_size),
+            new SimpleMutableEntry("ramColor", Theme.ram_color),
+            new SimpleMutableEntry("inputFieldBottom", Ui.input_bottom),
+            new SimpleMutableEntry("username", Ui.username),
+            new SimpleMutableEntry("showUsername", Ui.show_username_ssninfo),
+            new SimpleMutableEntry("showSubmit", Ui.show_enter_button),
+            new SimpleMutableEntry("deviceName", Ui.deviceName),
+            new SimpleMutableEntry("showRam", Ui.show_ram),
+            new SimpleMutableEntry("showDevice", Ui.show_device_name),
+            new SimpleMutableEntry("showToolbar", Toolbar.show_toolbar),
+            new SimpleMutableEntry("showSessionInfoWhenInputEmpty", Ui.show_ssninfo),
+            new SimpleMutableEntry("showPathInSessionInfo", Ui.show_path_ssninfo),
+            new SimpleMutableEntry("showDeviceNameInSessionInfo", Ui.show_devicename_ssninfo),
+
+            new SimpleMutableEntry("suggestionTextColor", Suggestions.default_text_color),
+            new SimpleMutableEntry("transparentSuggestions", Suggestions.transparent),
+            new SimpleMutableEntry("aliasSuggestionBg", Suggestions.alias_bg_color),
+            new SimpleMutableEntry("appSuggestionBg", Suggestions.apps_bg_color),
+            new SimpleMutableEntry("commandSuggestionsBg", Suggestions.cmd_bg_color),
+            new SimpleMutableEntry("songSuggestionBg", Suggestions.song_bg_color),
+            new SimpleMutableEntry("contactSuggestionBg", Suggestions.contact_bg_color),
+            new SimpleMutableEntry("fileSuggestionBg", Suggestions.file_bg_color),
+            new SimpleMutableEntry("defaultSuggestionBg", Suggestions.default_bg_color),
+
+            new SimpleMutableEntry("useSystemWallpaper", Ui.system_wallpaper),
+            new SimpleMutableEntry("fullscreen", Ui.fullscreen),
+            new SimpleMutableEntry("keepAliveWithNotification", Behavior.tui_notification),
+            new SimpleMutableEntry("openKeyboardOnStart", Behavior.auto_show_keyboard),
+
+            new SimpleMutableEntry("fromMediastore", Behavior.songs_from_mediastore),
+            new SimpleMutableEntry("playRandom", Behavior.random_play),
+            new SimpleMutableEntry("songsFolder", Behavior.songs_folder),
+
+            new SimpleMutableEntry("closeOnDbTap", Behavior.double_tap_closes),
+            new SimpleMutableEntry("showSuggestions", Suggestions.show_suggestions),
+            new SimpleMutableEntry("showDonationMessage", Behavior.donation_message),
+            new SimpleMutableEntry("showAliasValue", Behavior.show_alias_content),
+            new SimpleMutableEntry("showAppsHistory", Behavior.show_launch_history),
+
+            new SimpleMutableEntry("defaultSearch", Cmd.default_search)
+    };
+
+    private static XMLPrefsSave getCorresponding(String old) {
+        for(SimpleMutableEntry<String, XMLPrefsSave> s : OLD) {
+            if(old.equals(s.getKey())) return s.getValue();
+        }
+        return null;
+    }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationManager.java
index 4cc5328..d3d0f85 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationManager.java
@@ -2,6 +2,7 @@ package ohi.andre.consolelauncher.managers.notifications;
 
 import android.annotation.TargetApi;
 import android.os.Build;
+import android.util.Log;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -12,7 +13,10 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.regex.Pattern;
 
 import javax.xml.parsers.DocumentBuilder;
@@ -34,11 +38,17 @@ import static ohi.andre.consolelauncher.managers.XMLPrefsManager.writeTo;
 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
 public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
 
+    private static int TITLE = 10;
+    private static int TEXT = 11;
+
     private static final String COLOR_ATTRIBUTE = "color";
     private static final String ENABLED_ATTRIBUTE = "enabled";
+    private static final String ID_ATTRIBUTE = "id";
     private static final String ON_ATTRIBUTE = "on";
+    private static final String PACKAGE_ATTRIBUTE = "package";
 
-    private static final String REGEX_NODE = "regex";
+    private static final String FILTER_NODE = "filter";
+    private static final String APPLY_NODE = "apply";
 
     public static final String PATH = "notifications.xml";
     private static final String NAME = "NOTIFICATIONS";
@@ -50,11 +60,16 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
 
     public enum Options implements XMLPrefsManager.XMLPrefsSave {
 
-        enabled {
+        show_notifications {
             @Override
             public String defaultValue() {
                 return "false";
             }
+
+            @Override
+            public String hasReplaced() {
+                return "enabled";
+            }
         },
         default_app_state {
             @Override
@@ -65,7 +80,13 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
         default_color {
             @Override
             public String defaultValue() {
-                return "#FF0000";
+                return "#00FF00";
+            }
+        },
+        notification_format {
+            @Override
+            public String defaultValue() {
+                return "[%t] %pkg: %ttl --- %txt";
             }
         };
 
@@ -83,6 +104,16 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
         public boolean is(String s) {
             return name().equals(s);
         }
+
+        @Override
+        public String hasReplaced() {
+            return null;
+        }
+    }
+
+    @Override
+    public String[] deleted() {
+        return new String[0];
     }
 
     @Override
@@ -97,8 +128,8 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
 
     private static XMLPrefsManager.XMLPrefsList values;
     private static List<NotificatedApp> apps;
-    private static List<Pattern> titleRegexs;
-    private static List<Pattern> textRegexs;
+    private static List<FilterGroup> groups;
+    private static HashMap<Integer, String> applies;
     private static boolean created = false;
 
     private NotificationManager() {}
@@ -110,8 +141,8 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
         created = true;
 
         apps = new ArrayList<>();
-        textRegexs = new ArrayList<>();
-        titleRegexs = new ArrayList<>();
+        groups = new ArrayList<>();
+        applies = new HashMap<>();
         values = new XMLPrefsManager.XMLPrefsList();
 
         try {
@@ -140,6 +171,13 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
             }
             NodeList nodes = root.getElementsByTagName("*");
 
+            Map<String, XMLPrefsManager.XMLPrefsSave> replacedValues = new HashMap<>();
+            for(XMLPrefsManager.XMLPrefsSave s : Options.values()) {
+                String r = s.hasReplaced();
+                if(r != null) replacedValues.put(r, s);
+            }
+
+            Main:
             for(int count = 0; count < nodes.getLength(); count++) {
                 Node node = nodes.item(count);
 
@@ -153,16 +191,66 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
                             break;
                         }
                     }
-                } else if(nn.equals(REGEX_NODE)) {
+                } else if(nn.equals(FILTER_NODE)) {
                     if(node.getNodeType() == Node.ELEMENT_NODE) {
                         Element e = (Element) node;
-                        String regex = e.hasAttribute(REGEX_NODE) ? e.getAttribute(REGEX_NODE) : null;
+
+                        String regex = e.hasAttribute(VALUE_ATTRIBUTE) ? e.getAttribute(VALUE_ATTRIBUTE) : null;
                         if(regex == null) continue;
+
                         String on = e.hasAttribute(ON_ATTRIBUTE) ? e.getAttribute(ON_ATTRIBUTE) : null;
-                        if(on == null || on.equals("text") || !on.equals("title")) textRegexs.add(Pattern.compile(regex));
-                        else titleRegexs.add(Pattern.compile(regex));
+                        if(on == null) on = "text";
+
+                        int id;
+                        try {
+                            id = e.hasAttribute(ID_ATTRIBUTE) ? Integer.parseInt(e.getAttribute(ID_ATTRIBUTE)) : -1;
+                        } catch (NumberFormatException f) {
+                            id = -1;
+                        }
+
+                        Filter filter = Filter.getInstance(regex, on.equals("title") ? TITLE : TEXT);
+                        if(filter == null) continue;
+
+                        if(id != -1) {
+                            for(FilterGroup group : groups) {
+                                if(id == group.id) {
+                                    group.add(filter);
+                                    continue Main;
+                                }
+                            }
+                        }
+
+                        FilterGroup group = new FilterGroup(id);
+                        group.add(filter);
+                        groups.add(group);
+                    }
+                } else if(nn.equals(APPLY_NODE)) {
+                    if(node.getNodeType() == Node.ELEMENT_NODE) {
+                        Element e = (Element) node;
+
+                        int id;
+                        try {
+                            id = e.hasAttribute(ID_ATTRIBUTE) ? Integer.parseInt(e.getAttribute(ID_ATTRIBUTE)) : -1;
+                        } catch (NumberFormatException f) {
+                            continue;
+                        }
+
+                        String pkg = e.hasAttribute(PACKAGE_ATTRIBUTE) ? e.getAttribute(PACKAGE_ATTRIBUTE) : null;
+                        if(pkg == null) continue;
+
+                        applies.put(id, pkg);
                     }
-                } else {
+                } else if(replacedValues.containsKey(nn)) {
+                    XMLPrefsManager.XMLPrefsSave s = replacedValues.remove(nn);
+
+                    Element e = (Element) node;
+                    String oldValue = e.hasAttribute(VALUE_ATTRIBUTE) ? e.getAttribute(VALUE_ATTRIBUTE) : null;
+                    root.removeChild(e);
+
+                    replacedValues.put(oldValue, s);
+                }
+//                todo support delete
+                else {
                     if(node.getNodeType() == Node.ELEMENT_NODE) {
                         Element e = (Element) node;
 
@@ -179,38 +267,53 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
                 }
             }
 
-
             if(enums.size() > 0) {
+                Set<Map.Entry<String, XMLPrefsManager.XMLPrefsSave>> es = replacedValues.entrySet();
                 for(XMLPrefsManager.XMLPrefsSave s : enums) {
+                    String value = null;
+                    for(Map.Entry<String, XMLPrefsManager.XMLPrefsSave> e : es) {
+                        if(e.getValue().equals(s)) value = e.getKey();
+                    }
+                    if(value == null) value = s.defaultValue();
+
                     Element em = d.createElement(s.label());
-                    em.setAttribute(VALUE_ATTRIBUTE, s.defaultValue());
+                    em.setAttribute(VALUE_ATTRIBUTE, value);
                     root.appendChild(em);
 
-                    values.add(s.label(), s.defaultValue());
+                    values.add(s.label(), value);
                 }
 
                 writeTo(d, file);
             }
-        } catch (Exception e) {}
+        } catch (Exception e) {
+            Log.e("andre", "", e);
+        }
 
         default_app_state = XMLPrefsManager.get(boolean.class, Options.default_app_state);
         default_color = XMLPrefsManager.get(String.class, Options.default_color);
+
+        Out:
+        for(Map.Entry<Integer, String> e : applies.entrySet()) {
+            for(FilterGroup g : groups) {
+                if(g.applyTo(e.getKey(), e.getValue())) continue Out;
+            }
+        }
     }
 
     public static void notificationsChangeFor(NotificatedApp app) {
         notificationsChangeFor(new ArrayList<>(Collections.singletonList(app)));
     }
 
-    public static boolean textMatches(String text) {
-        if(text == null || text.length() == 0) return false;
-        for(Pattern p : textRegexs) if (p.matcher(text).matches()) return true;
+    public static boolean match(String pkg, String text, String title) {
+        for(FilterGroup group : groups) {
+            if(group.pkgs != null && !group.pkgs.contains(pkg)) continue;
+            if(group.check(title, text)) return true;
+        }
         return false;
     }
 
-    public static boolean titleMatches(String text) {
-        if(text == null || text.length() == 0) return false;
-        for(Pattern p : titleRegexs) if (p.matcher(text).matches()) return true;
-        return false;
+    public static String getFormat() {
+        return values.get(Options.notification_format).value;
     }
 
     public static void notificationsChangeFor(List<NotificatedApp> apps) {
@@ -228,8 +331,12 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
         setMany(new File(Tuils.getFolder(), PATH), NAME, names, attrNames, values);
     }
 
-    public static void excludeRegex(String regex, String on) {
-        XMLPrefsManager.set(new File(Tuils.getFolder(), PATH), NAME, REGEX_NODE, new String[] {ON_ATTRIBUTE, VALUE_ATTRIBUTE}, new String[] {on, regex});
+    public static void excludeRegex(String regex, String on, int id) {
+        XMLPrefsManager.add(new File(Tuils.getFolder(), PATH), NAME, FILTER_NODE, new String[] {ON_ATTRIBUTE, VALUE_ATTRIBUTE, ID_ATTRIBUTE}, new String[] {on, regex, id + Tuils.EMPTYSTRING});
+    }
+
+    public static void applyFilter(int groupId, String packageName) {
+        XMLPrefsManager.add(new File(Tuils.getFolder(), PATH), NAME, APPLY_NODE, new String[] {ID_ATTRIBUTE, PACKAGE_ATTRIBUTE}, new String[] {groupId + Tuils.EMPTYSTRING, packageName});
     }
 
     public static int apps() {
@@ -263,4 +370,65 @@ public class NotificationManager implements XMLPrefsManager.XmlPrefsElement {
             return pkg;
         }
     }
+
+    public static class Filter {
+        Pattern pattern;
+        int on;
+
+        public static Filter getInstance(String p, int on) {
+            Filter filter = new Filter(p, on);
+            if(filter.pattern == null) return null;
+            return filter;
+        }
+
+        private Filter(String p, int on) {
+            this.on = on;
+
+            try {
+                this.pattern = Pattern.compile(p);
+            } catch (Exception e) {
+                this.pattern = null;
+            }
+        }
+    }
+
+    public static class FilterGroup {
+        List<Filter> brothers;
+        int id;
+
+        List<String> pkgs;
+
+        public FilterGroup(int id) {
+            this.id = id;
+
+            brothers = new ArrayList<>();
+        }
+
+        public void add(Filter filter) {
+            brothers.add(filter);
+        }
+
+        public boolean check(String title, String text) {
+            for(Filter filter : brothers) {
+                String s;
+                if(filter.on == TITLE) s = title;
+                else s = text;
+
+                if(!filter.pattern.matcher(s).find()) return false;
+            }
+
+            return true;
+        }
+
+        public boolean applyTo(int id, String s) {
+            if(this.id == id) {
+                if(pkgs == null) pkgs = new ArrayList<>();
+
+                pkgs.add(s);
+                return true;
+            }
+
+            return false;
+        }
+    }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationService.java b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationService.java
index e2a4c62..f41300a 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationService.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/notifications/NotificationService.java
@@ -7,18 +7,28 @@ package ohi.andre.consolelauncher.managers.notifications;
 import android.annotation.TargetApi;
 import android.app.Notification;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.graphics.Color;
 import android.os.Build;
 import android.os.Handler;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.support.v4.content.LocalBroadcastManager;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.format.Time;
+import android.text.style.ForegroundColorSpan;
+import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
+import ohi.andre.consolelauncher.managers.XMLPrefsManager;
+import ohi.andre.consolelauncher.tuils.Tuils;
+
 import static ohi.andre.consolelauncher.managers.notifications.NotificationManager.NotificatedApp;
 import static ohi.andre.consolelauncher.managers.notifications.NotificationManager.default_color;
 
@@ -26,7 +36,7 @@ import static ohi.andre.consolelauncher.managers.notifications.NotificationManag
 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
 public class NotificationService extends NotificationListenerService {
 
-    private final int UPDATE_TIME = 200;
+    private final int UPDATE_TIME = 1500;
 
     Map<String, Long> recentNotifications = new HashMap<>();
     Handler handler = new Handler();
@@ -35,6 +45,8 @@ public class NotificationService extends NotificationListenerService {
     public void onCreate() {
         super.onCreate();
 
+        Log.e("andre", "hello");
+
         NotificationManager.create();
 
         if(NotificationManager.apps() == 0) {
@@ -54,11 +66,10 @@ public class NotificationService extends NotificationListenerService {
             @Override
             public void run() {
                 Map<String, Long> copy = new HashMap<>(recentNotifications);
+
                 long time = System.currentTimeMillis();
                 for(Map.Entry<String, Long> entry : copy.entrySet()) {
-                    if(time - entry.getValue() > 300) {
-                        recentNotifications.remove(entry.getKey());
-                    }
+                    if(time - entry.getValue() > 1500) recentNotifications.remove(entry.getKey());
                 }
 
                 handler.postDelayed(this, UPDATE_TIME);
@@ -71,6 +82,27 @@ public class NotificationService extends NotificationListenerService {
         return START_STICKY;
     }
 
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        Log.e("andre", "destroying notif");
+    }
+
+    Time time;
+    String timeFormat;
+    String format;
+    int timeColor;
+
+    final String FORMAT_PKG = "%pkg";
+    final String FORMAT_DATE = "%t";
+    final String FORMAT_TEXT = "%txt";
+    final String FORMAT_TITLE = "%ttl";
+    final String FORMAT_APPNAME = "%app";
+    final String FORMAT_NEWLINE = "%n";
+
+    PackageManager manager;
+
     @Override
     public void onNotificationPosted(StatusBarNotification sbn) {
 
@@ -82,8 +114,23 @@ public class NotificationService extends NotificationListenerService {
             return;
         }
 
+        if(time == null) {
+            time = new Time();
+            timeFormat = XMLPrefsManager.get(String.class, XMLPrefsManager.Behavior.time_format);
+            manager = getPackageManager();
+            format = NotificationManager.getFormat();
+            timeColor = XMLPrefsManager.getColor(XMLPrefsManager.Theme.time_color);
+        }
+
         String pack = sbn.getPackageName();
 
+        String appName;
+        try {
+            appName = manager.getApplicationInfo(pack, 0).loadLabel(manager).toString();
+        } catch (PackageManager.NameNotFoundException e) {
+            appName = "null";
+        }
+
         NotificatedApp nApp = NotificationManager.getAppState(pack);
         if( (nApp != null && !nApp.enabled)) {
             return;
@@ -111,7 +158,10 @@ public class NotificationService extends NotificationListenerService {
             title = titleSequence.toString();
         }
 
-        if(NotificationManager.textMatches(text) || NotificationManager.titleMatches(title)) return;
+        if(title == null) title = "null";
+        if(text == null) text = "null";
+
+        if(NotificationManager.match(pack, text, title)) return;
 
         int color;
         try {
@@ -120,11 +170,29 @@ public class NotificationService extends NotificationListenerService {
             color = Color.parseColor(default_color);
         }
 
+        SpannableString spanned = new SpannableString(format);
+        spanned.setSpan(new ForegroundColorSpan(color), 0, format.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        time.setToNow();
+        String t = this.time.format(timeFormat);
+        SpannableString spannedTime = new SpannableString(t);
+        spannedTime.setSpan(new ForegroundColorSpan(timeColor), 0, t.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        CharSequence s;
+        try {
+            s = TextUtils.replace(spanned,
+                    new String[] {FORMAT_PKG, FORMAT_APPNAME, FORMAT_DATE, FORMAT_TEXT, FORMAT_TITLE, FORMAT_NEWLINE,
+                            FORMAT_PKG.toUpperCase(), FORMAT_APPNAME.toUpperCase(), FORMAT_DATE.toUpperCase(), FORMAT_TEXT.toUpperCase(), FORMAT_TITLE.toUpperCase(), FORMAT_NEWLINE.toUpperCase()},
+                    new CharSequence[] {
+                            pack, appName, spannedTime, text, title, Tuils.NEWLINE, pack, appName, spannedTime, text, title, Tuils.NEWLINE
+                    }
+            );
+        } catch (Exception e) {
+            return;
+        }
+
         Intent msgrcv = new Intent("Msg");
-        msgrcv.putExtra("package", pack);
-        msgrcv.putExtra("title", title);
-        msgrcv.putExtra("text", text);
-        msgrcv.putExtra("color", color);
+        msgrcv.putExtra("text", s);
 
         LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(msgrcv);
     }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionsManager.java b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionsManager.java
index 46fe0c9..9a493dc 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionsManager.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/managers/suggestions/SuggestionsManager.java
@@ -42,7 +42,7 @@ public class SuggestionsManager {
     private final int MAX_RATE = 100;
     private final int NO_RATE = -1;
 
-    private final int FIRST_INTERVAL = 5;
+    private final int FIRST_INTERVAL = 7;
 
     private boolean showAlias, showAliasWasSet = false;
 
@@ -525,7 +525,9 @@ public class SuggestionsManager {
             if(type == Suggestion.TYPE_CONTACT) {
                 ContactManager.Contact c = (ContactManager.Contact) object;
 
-                return textBefore + Tuils.SPACE + c.numbers.get(c.selectedNumber);
+                if(c.numbers.size() <= c.getSelectedNumber()) c.setSelectedNumber(0);
+
+                return textBefore + Tuils.SPACE + c.numbers.get(c.getSelectedNumber());
             } else if(type == Suggestion.TYPE_PERMANENT) {
                 return text;
             }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/KeeperService.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/KeeperService.java
index 5187cc3..8b893c0 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/KeeperService.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/KeeperService.java
@@ -6,6 +6,7 @@ import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
 import android.support.v4.app.NotificationCompat;
+import android.util.Log;
 
 import ohi.andre.consolelauncher.LauncherActivity;
 import ohi.andre.consolelauncher.R;
@@ -46,5 +47,7 @@ public class KeeperService extends Service {
     @Override
     public void onDestroy() {
         super.onDestroy();
+
+        Log.e("andre", "destroying keep");
     }
 }
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/Sequence.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/Sequence.java
new file mode 100644
index 0000000..06a5e3b
--- /dev/null
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/Sequence.java
@@ -0,0 +1,81 @@
+package ohi.andre.consolelauncher.tuils;
+
+import android.support.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Created by francescoandreuzzi on 12/07/2017.
+ */
+
+public class Sequence {
+
+    List<Entry> sequence;
+
+    public Sequence(int[] keys, Object[] values) {
+        this.sequence = new ArrayList<>();
+
+        for(int count = 0; count < keys.length; count++) add(keys[count], values[count]);
+        Collections.sort(this.sequence);
+    }
+
+    public void add(int key, Object v) {
+        add(new Entry(key, v));
+    }
+
+    public void add(Entry e) {
+        int i = indexOf(e);
+        if(i == -1) this.sequence.add(e);
+        else {
+            e.key++;
+            i = indexOf(e);
+            if(i == -1) this.sequence.add(e);
+            else {
+                Entry x = sequence.remove(i);
+                sequence.add(e);
+                add(x);
+            }
+        }
+    }
+
+    public Object get(int index) {
+        return sequence.get(index).value;
+    }
+
+    public int size() {
+        return sequence.size();
+    }
+
+    private int indexOf(Entry e) {
+        for(int count = 0; count < sequence.size(); count++) if(e.equals(sequence.get(count))) return count;
+        return -1;
+    }
+
+    private class Entry implements Comparable<Entry> {
+        int key;
+        Object value;
+
+        public Entry(int key, Object value) {
+            this.key = key;
+            this.value = value;
+        }
+
+        @Override
+        public int compareTo(@NonNull Entry o) {
+            return this.key - o.key;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if(obj instanceof Entry) return key == ((Entry) obj).key;
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return key + ": " + value.toString();
+        }
+    }
+}
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/SimpleMutableEntry.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/SimpleMutableEntry.java
index 73a08a0..bb15c8d 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/SimpleMutableEntry.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/SimpleMutableEntry.java
@@ -28,14 +28,6 @@ public class SimpleMutableEntry<K, V> implements Map.Entry<K, V>, Serializable {
         value = theValue;
     }
 
-    /**
-     * Constructs an instance with the key and value of {@code copyFrom}.
-     */
-    public SimpleMutableEntry(Map.Entry<? extends K, ? extends V> copyFrom) {
-        key = copyFrom.getKey();
-        value = copyFrom.getValue();
-    }
-
     public K getKey() {
         return key;
     }
@@ -50,26 +42,8 @@ public class SimpleMutableEntry<K, V> implements Map.Entry<K, V>, Serializable {
         return result;
     }
 
-    @Override public boolean equals(Object object) {
-        if (this == object) {
-            return true;
-        }
-        if (object instanceof Map.Entry) {
-            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
-            return (key == null ? entry.getKey() == null : key.equals(entry
-                    .getKey()))
-                    && (value == null ? entry.getValue() == null : value
-                    .equals(entry.getValue()));
-        }
-        return false;
-    }
-
-    @Override public int hashCode() {
-        return (key == null ? 0 : key.hashCode())
-                ^ (value == null ? 0 : value.hashCode());
-    }
-
-    @Override public String toString() {
+    @Override
+    public String toString() {
         return key + "=" + value;
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/ohi/andre/consolelauncher/tuils/Tuils.java b/app/src/main/java/ohi/andre/consolelauncher/tuils/Tuils.java
index 396f3f0..43bc6d5 100755
--- a/app/src/main/java/ohi/andre/consolelauncher/tuils/Tuils.java
+++ b/app/src/main/java/ohi/andre/consolelauncher/tuils/Tuils.java
@@ -20,17 +20,23 @@ import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Build;
 import android.os.Environment;
+import android.os.StatFs;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 
+import java.io.BufferedReader;
 import java.io.DataOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Enumeration;
@@ -164,11 +170,184 @@ public class Tuils {
         a.startActivity(intent);
     }
 
-    public static String ramDetails(ActivityManager mgr, MemoryInfo info) {
+    public static Intent webPage(String url) {
+        return new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+    }
+
+    public static double getAvailableInternalMemorySize(int unit) {
+        File path = Environment.getDataDirectory();
+        StatFs stat = new StatFs(path.getPath());
+
+        long blockSize;
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+            blockSize = stat.getBlockSizeLong();
+        } else {
+            blockSize = stat.getBlockSize();
+        }
+
+        long availableBlocks = 0;
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+            availableBlocks = stat.getAvailableBlocksLong();
+        } else {
+            availableBlocks = stat.getAvailableBlocks();
+        }
+
+        return formatSize(availableBlocks * blockSize, unit);
+    }
+
+    public static double getTotalInternalMemorySize(int unit) {
+        File path = Environment.getDataDirectory();
+        StatFs stat = new StatFs(path.getPath());
+
+        long blockSize;
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+            blockSize = stat.getBlockSizeLong();
+        } else {
+            blockSize = stat.getBlockSize();
+        }
+
+        long totalBlocks = 0;
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+            totalBlocks = stat.getBlockCountLong();
+        } else {
+            totalBlocks = stat.getBlockCount();
+        }
+
+        return formatSize(totalBlocks * blockSize, unit);
+    }
+
+    public static double getAvailableExternalMemorySize(int unit) {
+        if (externalMemoryAvailable()) {
+            File path = Environment.getExternalStorageDirectory();
+            StatFs stat = new StatFs(path.getPath());
+
+            long blockSize;
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+                blockSize = stat.getBlockSizeLong();
+            } else {
+                blockSize = stat.getBlockSize();
+            }
+
+            long availableBlocks = 0;
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+                availableBlocks = stat.getAvailableBlocksLong();
+            } else {
+                availableBlocks = stat.getAvailableBlocks();
+            }
+
+            return formatSize(availableBlocks * blockSize, unit);
+        } else {
+            return -1;
+        }
+    }
+
+    public static double getTotalExternalMemorySize(int unit) {
+        if (externalMemoryAvailable()) {
+            File path = Environment.getExternalStorageDirectory();
+            StatFs stat = new StatFs(path.getPath());
+
+            long blockSize;
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+                blockSize = stat.getBlockSizeLong();
+            } else {
+                blockSize = stat.getBlockSize();
+            }
+
+            long totalBlocks = 0;
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
+                totalBlocks = stat.getBlockCountLong();
+            } else {
+                totalBlocks = stat.getBlockCount();
+            }
+
+            return formatSize(totalBlocks * blockSize, unit);
+        } else {
+            return -1;
+        }
+    }
+
+    public static double percentage(double part, double total) {
+        return round(part * 100 / total, 2);
+    }
+
+    public static boolean externalMemoryAvailable() {
+        return android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
+    }
+
+    public static double formatSize(long bytes, int unit) {
+        double convert = 1048576.0;
+        double smallConvert = 1024.0;
+
+        double result;
+
+        switch (unit) {
+            case TERA:
+                result = (bytes / convert) / convert;
+                break;
+            case GIGA:
+                result = (bytes / convert) / smallConvert;
+                break;
+            case MEGA:
+                result = bytes / convert;
+                break;
+            case KILO:
+                result = bytes / smallConvert;
+                break;
+            case BYTE:
+                result = bytes;
+                break;
+            default: return -1;
+        }
+
+        return round(result, 2);
+    }
+
+    public static int max(int... ints) {
+        int max = ints[0];
+        for(int count = 1; count < ints.length; count++) {
+            max = Math.max(max, ints[count]);
+        }
+        return max;
+    }
+
+    public static final int TERA = 0;
+    public static final int GIGA = 1;
+    public static final int MEGA = 2;
+    public static final int KILO = 3;
+    public static final int BYTE = 4;
+    public static final int PERCENTAGE = 5;
+
+    private static long total = -1;
+
+    public static double freeRam(ActivityManager mgr, MemoryInfo info) {
         mgr.getMemoryInfo(info);
-        long availableMegs = info.availMem / 1048576L;
+        return info.availMem;
+    }
+
+    public static long totalRam() {
+        if(total > 0) return total;
 
-        return availableMegs + " MB";
+        BufferedReader reader;
+        try {
+            reader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/meminfo")));
+
+            String line;
+            while((line = reader.readLine()) != null) {
+                if(line.startsWith("MemTotal")) {
+                    line = line.replaceAll("\\D+", Tuils.EMPTYSTRING);
+                    return Long.parseLong(line);
+                }
+            }
+        } catch (Exception e) {}
+        return 0;
+    }
+
+    public static double round(double value, int places) {
+        if (places < 0) throw new IllegalArgumentException();
+
+        BigDecimal bd = new BigDecimal(value);
+        bd = bd.setScale(places, RoundingMode.HALF_UP);
+        return bd.doubleValue();
     }
 
     public static List<String> getClassesInPackage(String packageName, Context c) throws IOException {
@@ -211,19 +390,23 @@ public class Tuils {
         for(int count = 0; count < list.size(); count++) {
             Object x = list.get(count);
 
-            if(o instanceof XMLPrefsManager.XMLPrefsSave) {
+            if (o instanceof XMLPrefsManager.XMLPrefsSave) {
                 try {
-                    if(((XMLPrefsManager.XMLPrefsSave) o).is((String) x)) return count;
+                    if (((XMLPrefsManager.XMLPrefsSave) o).is((String) x)) return count;
                 } catch (Exception e) {}
             }
 
-            if(o instanceof String && x instanceof XMLPrefsManager.XMLPrefsSave) {
+            if (o instanceof String && x instanceof XMLPrefsManager.XMLPrefsSave) {
                 try {
-                    if(((XMLPrefsManager.XMLPrefsSave) x).is((String) o)) return count;
+                    if (((XMLPrefsManager.XMLPrefsSave) x).is((String) o)) return count;
                 } catch (Exception e) {}
             }
 
-            if(o.equals(x) || x.equals(o)) return count;
+            try {
+                if (o.equals(x) || x.equals(o)) return count;
+            } catch (Exception e) {
+                continue;
+            }
         }
         return -1;
     }
diff --git a/app/src/main/res/layout/about_device_view.xml b/app/src/main/res/layout/about_device_view.xml
index 758411b..3d44049 100755
--- a/app/src/main/res/layout/about_device_view.xml
+++ b/app/src/main/res/layout/about_device_view.xml
@@ -4,21 +4,23 @@
     android:layout_height="wrap_content"
     android:orientation="vertical">
 
-    <TextView
-        android:id="@+id/deviceinfo_tv"
+    <TextView android:id="@+id/tv0"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
-    <TextView
-        android:id="@+id/ram_tv"
+    <TextView android:id="@+id/tv1"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
-    <TextView android:id="@+id/battery_tv"
+    <TextView android:id="@+id/tv2"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
-    <TextView android:id="@+id/time_tv"
+    <TextView android:id="@+id/tv3"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <TextView android:id="@+id/tv4"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" />
 
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 99ea4d5..83d5e4b 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,12 +11,15 @@
     <string name="version_label">Version:</string>
     <string name="output_error">An unknown error has occurred</string>
     <string name="location_off">Turn on GPS or network location</string>
+    <string name="invalid_integer">Invalid integer</string>
 
     <!-- busy -->
     <string name="busy">T-UI is busy, wait until the execution finishes or use the command \"ctrlc\"</string>
     <string name="busy_hint">type \"ctrlc\" to stop</string>
 
-    <string name="rate_donate_text">\nDo you like my work? Rate on Play Store (command: >>rate) or offer me a coffee (command: >>donate). Thank you for using T-UI.\n\nYou can disable this message in >>tuisettings</string>
+    <string name="rate_donate_text">\nDo you like my work? Rate on Play Store (command: >>rate) or offer me a coffee (command: >>donate). Thank you for using T-UI.
+        \n\nYou can disable this message with the command "config -set donation_message false"</string>
+    <string name="firsthelp_text">First time with t-ui? Use the command "tutorial" or "help"</string>
 
     <!-- app mgr -->
     <string name="output_appnotfound">Application not found</string>
@@ -30,6 +33,7 @@
 
     <!-- pending operation -->
     <string name="calling">Calling:</string>
+    <string name="restarting">t-ui will be closed in some seconds. Click the home button to restart it</string>
 
     <!-- various outputs -->
     <string name="output_nothingfound">No matches</string>
@@ -158,15 +162,19 @@
         \n\n>>calc sqrt25
         \n5
     </string>
-    <string name="help_call">Perform a call to someone or print your contacts
-        \nUsage: call [number] OR [name] (if you don\'t specify a number or a name you will get the list of your contacts)
-        \n\n>>call James
+    <string name="help_call">Make a call
+        \nUsage: call [number] OR [name]
+        \n\nExample:
+        \n>>call James
+        \n>>call 3283456789
     </string>
+    <string name="help_community">Go to the t-ui community on Google+</string>
     <string name="help_config">Manage your config files.
         \nUsage:
         \n>>config [option] [file OR config_entry] [*value]
         \n\n-set -> set the value of a config node
         \n-open -> open a config file
+        \n-get -> get the value of an option
         \n\nExample:
         \n>>config -set bg_color #ff0000aa
         \n>>config -open suggestions.xml</string>
@@ -237,7 +245,7 @@
         \n\n-rm -> remove t-ui
         \n-about -> show info about the developer and the current version</string>
         \n-reset -> Removes t-ui folder and resets default settings (restart required)
-    <string name="help_tutorial">Go to T-UI tutorial page</string>
+    <string name="help_tutorial">Open the tutorial page on GitHub</string>
     <string name="help_uninstall">Uninstall an application
         \nUsage:
         \n>>uninstall appName OR packageName
@@ -261,12 +269,14 @@
         \nUsage:
         \n>>beep</string>
     <string name="help_notifications">Manage your notifications.
-        \nUsage:
-        \nnotifications [option] [appName] [*optional* color]
         \n\n-inc -> include an application
-        \n-exc -> exclude an appliation
+        \n-exc -> exclude an application
         \n-clr -> set the color to be used for the application
         \n-file -> open notifications.xml
+        \n-title_filter -> set a filter over notifications title ([id] [regex])
+        \n-text_filter -> set a filter over notifications text ([id] [regex])
+        \n-apply_filter -> apply a filter to a particular application ([id] [application])
+        \n-access -> show the system settings page dedicated to the Notification Access
         \n\nExample:
         \n\nnotifications -inc Clock
         \nnotifications -clr Settings #FF0000</string>
-- 
GitLab