User Tools

Site Tools


script_autosetupappfreeze

====== Differences ====== This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
script_autosetupappfreeze [2016/08/29 12:50]
cdfa
script_autosetupappfreeze [2017/07/21 08:57] (current)
cdfa 1.8.4
Line 4: Line 4:
   * Initial request: https://​plus.google.com/​+JaroslavGrochal/​posts/​BDKDMrTMfxt   * Initial request: https://​plus.google.com/​+JaroslavGrochal/​posts/​BDKDMrTMfxt
   * GitHub: https://​github.com/​cdfa/​AutoSetupLongTapFreeze   * GitHub: https://​github.com/​cdfa/​AutoSetupLongTapFreeze
-  * Version: 1.7+  * Version: 1.8.4
  
 ====== How to use the script ====== ====== How to use the script ======
  
-Run script in any container to run setup freezing and unfreezing actions for all items. The action is configurable at the top of the script. You can setup autosync in the setup, or you can sync manually from any item put in the container by running the script with "​sync"​ (without the") as data, or from anywhere if you put the container id directly behind it, so like (sync1).+Run script in any container to run setup freezing and unfreezing actions for all items. The action is configurable at the top of the script.
  
-You can sync items separately ​from the items menu and choosing Sync from the menu. If the menu is opened in any other way then is specified at the top of the script extra items won't be there.+You can setup autosync in the setup, or you can sync manually ​from the container ​menu => items => sync, or you can run the script from any item in the container with "​sync"​ (without ​the ""​) as data, or from anywhere if you put the container id directly behind it, so like "​sync1"​.
  
-Run the script ​from the container again to uninstall (this won't clear events you manually set to sync the container).+You can sync items separately ​from the item menu and choosing Sync, or sync all items in a container ​also from the item menu. This can also be done when the items are in a folder by longpressing the folder item.
  
-Run the script from the lightning menu to uninstall ​from every container.+Run the script from the container again to uninstall ​(this won't clear events you manually set to sync the container).
  
 Please report all issues at the GitHub page. Please report all issues at the GitHub page.
  
 ====== Changelog ====== ====== Changelog ======
-  ​Multithreading! ​LL won'​t ​get stuck anymore ​when executing a root command!+1.8 
 +  ​Updated to LL 14b7 
 +  * sync action is now in the items menu in the container menu as well 
 +  * uninstall everywhere function is lost for now, because i cannot distinguish between the menu from the menu of a container anymore. Please suggest new triggers if you want this functionality back. 
 + 
 +1.8.1 
 +  * workaround for double comfirm crash in LL14 
 + 
 +1.8.1.1 
 +  * Added item description to the toast message that is displayed if the item doesn'​t ​launch an app 
 + 
 +1.8.1.2 
 +  * Made the changes in 1.8.1.1 actually work 
 + 
 +1.8.1.3 
 +  * Toasts message that says the item doesn'​t launch an app now only shows when you're actually trying to freeze that item and not anymore on each sync. 
 + 
 +1.8.2 
 +  * The double confirm crash got fixed, so the workaround was removed 
 +  * Only commands that need root are executed as root 
 + 
 +1.8.3 
 +  * Added freezeing/​unfreezing all item from menu 
 +  * Added long press folder to freeze/​unfreeze all items in it 
 + 
 +1.8.4 
 +  * Ask to unfreeze and run an item if it is frozen instead of saying that the app is not installed
  
 ====== Script code ====== ====== Script code ======
Line 26: Line 52:
   , whiteList = []   , whiteList = []
   // for Sources see: http://​www.lightninglauncher.com/​scripting/​reference/​api/​reference/​net/​pierrox/​lightning_launcher/​script/​api/​Event.html   // for Sources see: http://​www.lightninglauncher.com/​scripting/​reference/​api/​reference/​net/​pierrox/​lightning_launcher/​script/​api/​Event.html
-  // for Event see http://​www.lightninglauncher.com/​scripting/​reference/​api/​reference/​net/​pierrox/​lightning_launcher/​script/​api/​PropertySet.html +  // for Events ​see http://​www.lightninglauncher.com/​scripting/​reference/​api/​reference/​net/​pierrox/​lightning_launcher/​script/​api/​PropertySet.html
-  // you may only have to set 1 in the future.+
   , freezeSource = "​I_LONG_CLICK"​   , freezeSource = "​I_LONG_CLICK"​
-  , freezeEvent = "​i.longTap+  , freezeEvent = "​i.longTap";​
-  , menuSource = "​I_SWIPE_UP"​ +
-  , menuEvent = "​i.swipeUp";+
  
-LL.bindClass("​android.app.AlertDialog"); +bindClass("​android.widget.Toast"); 
-LL.bindClass("​android.content.DialogInterface"); +bindClass("​android.content.pm.PackageManager"); 
-LL.bindClass("​android.widget.Toast"); +bindClass("​java.lang.Thread"); 
-LL.bindClass("​android.content.pm.PackageManager"); +bindClass("​android.os.Handler"); 
-LL.bindClass('java.lang.Runtime'​); +bindClass("​android.os.Looper"​); 
-LL.bindClass('​java.io.DataInputStream'); +bindClass('​java.io.BufferedReader'); 
-LL.bindClass('​java.io.DataOutputStream'); +bindClass('​java.io.InputStreamReader'); 
-LL.bindClass('​java.lang.StringBuffer'); +bindClass('​java.io.DataOutputStream'); 
-LL.bindClass("java.lang.Runnable"​); +bindClass('java.lang.StringBuffer'​); 
-LL.bindClass("java.lang.Thread"​);​ +bindClass('java.lang.Runtime'​);
-LL.bindClass("​android.os.Handler"​);​ +
-LL.bindClass("​android.os.Looper"​);+
  
-var LL.getEvent() +var script ​getCurrentScript() 
-  , it e.getItem() +  , screen ​getActiveScreen() 
-  , script = LL.getCurrentScript() +  , context = screen.getContext()
-  , context = LL.getContext() +
-  , data = e.getData() +
-  , frozenItIdss = []+
   , threads = []   , threads = []
   , GUIHandler = new Handler()   , GUIHandler = new Handler()
   , frozenApps;   , frozenApps;
-  + 
-function ​loanEventHandler(ob, name, action, data){+function ​setEventHandlerRestorably(ob, name, action, data){
   var prop = ob.getProperties()   var prop = ob.getProperties()
     , ed = prop.edit()     , ed = prop.edit()
Line 63: Line 81:
   ed.setEventHandler(name,​ action, data);   ed.setEventHandler(name,​ action, data);
   ed.commit();​   ed.commit();​
-  ob.setTag("​old "​+name+"​ evHa", JSON.stringify(evHa));​+  ob.setTag("​old " + name + " evHa", JSON.stringify(evHa));​
 } }
-  + 
-function ​returnEventHandler(ob, name){ +function ​restoreEventHandler(ob, name){ 
-  ​var ed = ob.getProperties().edit(+  ​if(ob){ 
-    ​evHa = JSON.parse(ob.getTag("​old "​+name+"​ evHa"​));​ +    ​var evHa = JSON.parse(ob.getTag("​old " + name + " evHa"​));​ 
-  ed.setEventHandler(name,​ evHa[0], evHa[1]); +    ​if(evHa){ 
-  ed.commit();​ +      var ed = ob.getProperties().edit();​ 
-  ob.setTag("​name",​ null); +      ​ed.setEventHandler(name,​ evHa[0], evHa[1]); 
-} +      ed.commit();​ 
-  +      ob.setTag("​name",​ null); 
-function customConfirmDialog(title,​onConfirmFunction)+    }else
-  var builder=new AlertDialog.Builder(context); +      ​throw ​new Error("No eventhandler backup for " + name + " on " + ob + "​found!"​
-  ​builder.setCancelable(true);​ +    } 
-  ​builder.setTitle(title);​ +  ​}else{ 
-  ​builder.setNegativeButton("Cancel",new DialogInterface.OnClickListener(){onClick:​function(dialog,​id){dialog.dismiss();​}});​ +    throw new Error("Cannot restore ​" ​+ name + "of null!") 
-  builder.setPositiveButton("Confirm",new DialogInterface.OnClickListener(){onClick:​function(dialog,​id){dialog.dismiss();​setTimeout(onConfirmFunction,​0);​}});​ +  ​}
-  ​builder.show();​+
 } }
- +
 function uninstall(c){ function uninstall(c){
-  if(c){ +  if(c && c.getTag("​longTapFreeze"​)){ 
-    c.setTag("​longTapFreeze",​false);​ +    c.setTag("​longTapFreeze",​ false); 
-    ​returnEventHandler(c, freezeEvent);​ +    ​restoreEventHandler(c, freezeEvent);​ 
-    ​returnEventHandler(c, menuEvent); +    ​restoreEventHandler(c, '​i.tap'​);​ 
-    if(c.getTag("​autosync"​)=="​true"​)returnEventHandler(c, "​resumed"​);​ +    restoreEventHandler(c,​ "​i.menu"​);​ 
-    ​var frozenItIds = getFrozenItIds(c) +    restoreEventHandler(c,​ "​menu"​); 
-      , it; +    if(c.getTag("​autosync"​) ​=== "​true"​) ​restoreEventHandler(c, "​resumed"​);​ 
-    frozenItIds.forEach(function(itId, ind){ +    ​c.getAllItems().forEach(function(it){ 
-      if(it = c.getItemById(itId)){+      if(isFrozen(it))
         unfreezeEffect(it);​         unfreezeEffect(it);​
 +    });
 +    var cs = screen.getAllContainersById(c.getId());​
 +    cs.forEach(function(c){
 +      var opener;
 +      if((opener = c.getOpener()) && opener.getType() === "​Folder"​){
 +        if(isFrozen(opener))
 +          unfreezeEffect(opener);​
       }       }
 +    });
 +  }
 +}
 +
 +/**
 + * Checks if an object is an array.
 + * @param object
 + * @returns {boolean}
 + */
 +function isArray(object){
 +  return Object.prototype.toString.call(object) === '​[object Array]';​
 +}
 +
 +/**
 + * If this function is executed in a thread that is the main GUI thread, execute func, or else execute func in the main GUI thread. (Android doesn'​t like it when you change the GUI outside of the main GUI thread)
 + * @param func {function}
 + */
 +function handleGUIEdit(func){
 +  if(Looper.getMainLooper().getThread() === Thread.currentThread()){
 +    func();
 +  }else{
 +    GUIHandler.post(func);​
 +  }
 +}
 +
 +/**
 + * Starts a new background thread with func.
 + * @param func {function} - The function the thread executes.
 + */
 +function startNewBackgroundThread(func){
 +  var thread = new Thread(function(){
 +    func();
 +    // if a looper was initialized in func, make sure the thread can die by stopping the thread when the Looper idles.
 +    if(threads[Thread.currentThread().getId()].prepared === true){
 +      Looper.myLooper().getQueue().addIdleHandler(function(){
 +        Looper.myLooper().quitSafely();​
 +      });
 +      Looper.loop();​
 +    }
 +  });
 +  thread.setUncaughtExceptionHandler(function(th,​ ex){
 +    handleGUIEdit(function(){
 +      alert(ex.getMessage());​
     })     })
-    frozenItIds.clear(); +  }); 
-    ​frozenItIds.queueSave();+  threads[thread.getId()] = {}; 
 +  thread.start();​ 
 +
 + 
 +//​noinspection JSValidateJSDoc 
 +/** 
 + * Gets a handler for the current thread and initializes a looper if necessary. 
 + * @returns {Handler} 
 + */ 
 +function getHandler(){ 
 +  if(Looper.getMainLooper().getThread() === Thread.currentThread()){ 
 +    ​return GUIHandler;​ 
 +  }else{ 
 +    var threadId = Thread.currentThread().getId();​ 
 +    if(threads[threadId].prepared !== true){ 
 +      Looper.prepare();​ 
 +      threads[threadId].prepared = true; 
 +    } 
 +    return new Handler();
   }   }
 } }
  
-function runAsRoot(cmd, newThread, callback{ +/** 
-  ​function execCmd(cmd){ + * This callback will be called when the executing of the command(sis finished 
-    ​try ​+ 
-      var process ​Runtime.getRuntime().exec("​su"​) + * @callback finishedCallback 
-        , reader ​= new DataInputStream(process.getInputStream()) + * @param {string[]} An array of the lines the command(sreturned 
-        , writer = new DataOutputStream(process.getOutputStream());+ */ 
 +/** 
 + * This callback will be called when a command is executed. 
 + * 
 + * @callback executedCallback 
 + */ 
 +/** 
 + * Runs a command in the terminal 
 + * @param cmds {string|string[]} - The command or array of commmands to be executed. 
 + * @param [asRoot=false] {boolean} - If the command(sshould be executed as root or not
 + * @param [newThread=true] {boolean} - If the executing of commands should happen in a new thread or not. (useful for root commands) 
 + * @param [callback] {finishedCallback} - The callback that handles the output. 
 + * @param [onExecuted] {executedCallback} - A callback that will be called when a command is executed. useful for multiple commands that take some time
 + * @returns {string[]||string[][]} - (only if asRoot == false && newThread == false) Returns an array of the lines written in the terminal or an array of arrays if multiple commands were executed. 
 + */ 
 +function runCmd(cmds, asRoot, newThread, callback, onExecuted)
 +  var handler = getHandler() 
 +    , output, process, reader, writer;
  
-      writer.writeBytes(cmd + '​\n'​);​ +  // set optional arguments 
-      ​writer.flush(); +  if(newThread !== false
-      ​writer.close();+    ​newThread = true;
  
-      var tmp +  /** 
-        , output = []; +   * Helper function for executing the command(s). Gets its parameters from the parent function. 
-      ​while ((tmp reader.readLine()) != null) { +   * @returns {string[]||string[][]} - (only if asRoot == false && newThread == false) Returns an array of the lines written in the terminal or an array of arrays if multiple commands were executed. 
-        ​output.push(tmp);+   */ 
 +  function execCmd(){ 
 +    /** 
 +     * Checks if the command is a string and if not alerts the user. 
 +     * @param cmd {string} 
 +     * @returns {boolean} 
 +     */ 
 +    function checkCmd(cmd){ 
 +      ​if(typeof(cmd) === "​string"​){ 
 +        return true; 
 +      }else 
 +        handleGUIEdit(function(){ 
 +          alert(cmd + " is not a string!"​);​ 
 +        }); 
 +      return false; 
 +    } 
 + 
 +    //​noinspection JSValidateJSDoc 
 +    /** 
 +     * Actually executes command. 
 +     * @param cmd {string} 
 +     * @param writer {DataOutputStream} - The writer to write the command to. 
 +     * @returns {boolean} If the command was actually written or not. 
 +     */ 
 +    function exec(cmd, writer)
 +      if(checkCmd(cmd)){ 
 +        ​writer.writeBytes(cmd + "​\n"​)
 +        writer.flush();​ 
 +        return true;
       }       }
-      ​reader.close();​ +      return ​false;
-      process.waitFor();​ +
-      ​return ​output; +
-    } catch (err) { +
-      alert(err+"​At line "​+err.lineNumber);+
     }     }
-  ​+ 
-   +    //​noinspection JSValidateJSDoc 
-  if(newThread==false){ +    /** 
-    ​return execCmd(cmd); +     * Read the output from the reader. 
-  ​}else{ +     * @param reader {BufferedReader
-    var handler ​getHandler()+     * @returns {Array} An array of lines that were outputted by the 
-    ​startNewBackgroundThread(function(){ +     */ 
-      if(callback){ +    function readOutput(reader){ 
-        var output ​execCmd(cmd);+      var tmp, output ​[]; 
 +      while((tmp ​reader.readLine()) !== null
 +        ​output.push(tmp); 
 + 
 +      ​return output.length ​=== 1 ? output[0] : output
 +    ​
 + 
 +    /** 
 +     * Executes the callback and if the callback is not a function alerts the user. 
 +     * @param callback 
 +     * @param output {Array} - The argument that is passed to the callback 
 +     */ 
 +    ​function ​handleCallback(callback, output){ 
 +      if(typeof ​callback === "​function"​){
         handler.post(function(){         handler.post(function(){
           callback(output);​           callback(output);​
         });         });
 +      }else if(callback){
 +        handleGUIEdit(function(){
 +          alert(callback + " is not a function!"​);​
 +        });
 +      }
 +    }
 +
 +    try{
 +      if(asRoot){
 +        process = Runtime.getRuntime().exec("​su"​);​
 +        reader = new BufferedReader(new InputStreamReader(process.getInputStream()));​
 +        writer = new DataOutputStream(process.getOutputStream());​
 +
 +        if(isArray(cmds)){
 +          output = [];
 +          cmds.forEach(function(cmd){
 +            if(exec(cmd,​ writer)){
 +              handleCallback(onExecuted);​
 +            }
 +          });
 +
 +          exec("​exit",​ writer);
 +          writer.close();​
 +
 +          output = readOutput(reader);​
 +          handleCallback(callback,​ output);
 +        }else{
 +          var succes = exec(cmds, writer);
 +
 +          exec("​exit",​ writer);
 +          writer.close();​
 +
 +          if(succes){
 +            output = readOutput(reader);​
 +            handleCallback(onExecuted);​
 +            handleCallback(callback,​ output);
 +          }
 +        }
 +
 +        reader.close();​
 +        process.waitFor();​
       }else{       }else{
-        ​execCmd(cmd)+        ​if(isArray(cmds)){ 
 +          var outputs = []; 
 +          cmds.forEach(function(cmd)
 +            if(checkCmd(cmd)){ 
 +              process = Runtime.getRuntime().exec(cmd);​ 
 +              reader = new BufferedReader(new InputStreamReader(process.getInputStream()));​ 
 +              output = readOutput(reader);​ 
 +              reader.close();​ 
 +              outputs.push(output);​ 
 +              handleCallback(onExecuted);​ 
 +              handleCallback(callback,​ output); 
 +            } 
 +          }); 
 +          process.waitFor();​ 
 +          return outputs; 
 +        }else{ 
 +          process = Runtime.getRuntime().exec(cmds);​ 
 +          reader = new BufferedReader(new InputStreamReader(process.getInputStream()));​ 
 +          output = readOutput(reader);​ 
 +          reader.close();​ 
 +          process.waitFor();​ 
 +          handleCallback(onExecuted);​ 
 +          handleCallback(callback,​ output); 
 +          return output; 
 +        }
       }       }
-    })+    }catch(err)
 +      handleGUIEdit(function(){ 
 +        alert("​At line " + err.lineNumber + ": " + err); 
 +      }); 
 +    } 
 +  } 
 + 
 +  if(asRoot && isArray(callback)) 
 +    throw new Error("​Multiple callbacks are not possible in su mode. Use onExecuteds instead."​);​ 
 + 
 +  if(newThread){ 
 +    startNewBackgroundThread(function(){ 
 +      execCmd();​ 
 +    }); 
 +  }else{ 
 +    return execCmd();
   }   }
 } }
Line 146: Line 365:
     return it.getIntent().getComponent().getPackageName();​     return it.getIntent().getComponent().getPackageName();​
   }catch(e){   }catch(e){
-    Toast.makeText(context,​ "This item doesn'​t launch an app!", Toast.LENGTH_SHORT).show();​ 
     return null;     return null;
   }   }
Line 154: Line 372:
   if(!pkgName)   if(!pkgName)
     return false;     return false;
-  ​ 
-  var onBlackList = false; 
-  for(var i=0;​i<​blackList.length;​i++){ 
-    if(pkgName==blackList[i]){ 
-      onBlackList=true;​ 
-      break; 
-    } 
-  } 
  
-  if(whiteList.length==0){+  ​var onWhiteList,​ 
 +    onBlackList = blackList.some(function(pkg){ 
 +      return pkg === pkgName; 
 +    }); 
 + 
 +  ​if(whiteList.length ​=== 0){
     onWhiteList = true;     onWhiteList = true;
   }else{   }else{
-    onWhiteList = false; +    onWhiteList = whiteList.some(function(pkg){ 
-    for(var i=0;i<whiteList.length;i++){ +      ​return pkg === pkgName
-      ​if(pkgName==whiteList[i]){ +    });
-        onWhiteList=true; +
-        break; +
-      } +
-    }+
   }   }
-  ​+
   return !onBlackList && onWhiteList;​   return !onBlackList && onWhiteList;​
 } }
  
-function ​freeze(it, pkgName){ +function ​freezeChecks(it, allGood, giveFeedback){ 
-  ​runAsRoot("​pm disable "+pkgName, true, function(){ +  ​var pkgName ​= getPackageName(it
-    ​freezeEffect(it); +    ​, freezeAble = isFreezable(pkgName); 
-    ​var frozenItIds = getFrozenItIds(it.getParent()); +  if(pkgName && freezeAble){ 
-    ​frozenItIds.push(it.getId()); +    ​allGood(pkgName); 
-    ​frozenItIds.queueSave(); +  }else if(giveFeedback !== false){ 
-  });+    ​if(!pkgName) 
 +      Toast.makeText(context, ​it + " doesn'​t launch an app!", Toast.LENGTH_SHORT).show(); 
 +    ​else if(!freezeAble) 
 +      Toast.makeText(context,​ "​Cannot freeze/​unfreeze! (Probably because of black- or whitelist",​ Toast.LENGTH_SHORT).show(); 
 +  }
 } }
  
-function ​unfreeze(it, pkgName){ +function ​freeze(it, callback){ 
-  ​runAsRoot("​pm ​enable ​"​+pkgName,​ true, function(){ +  ​if(it.getType() === "​Folder"​){ 
-    ​unfreezeEffect(it); +    freezeContainer(it.getContainer());​ 
-    var frozenItIds ​getFrozenItIds(it.getParent()); +  }else{ 
-    ​frozenItIds.remove(it.getId()); +    freezeChecks(it,​ function(pkgName){ 
-    ​frozenItIds.queueSave(); +      runCmd("​pm ​disable ​" + pkgName, true, true, null, function(){ 
-  });+        ​freezeEffect(it); 
 +        ​if(typeof callback ​=== '​function'​) 
 +          callback();​ 
 +      }); 
 +    }); 
 +  } 
 +
 + 
 +function unfreeze(it,​ callback){ 
 +  if(it.getType() === "​Folder"​){ 
 +    ​unfreezeContainer(it.getContainer()); 
 +  }else{ 
 +    ​freezeChecks(it, function(pkgName){ 
 +      runCmd("​pm enable " + pkgName, true, true, null, function(){ 
 +        unfreezeEffect(it); 
 +        ​if(typeof callback === '​function'​) 
 +          callback();​ 
 +      ​}); 
 +    }); 
 +  }
 } }
  
 function freezeEffect(it){ function freezeEffect(it){
-  it.getProperties().edit().setInteger("​s.iconColorFilter",​0x00ffffff).commit();​ +  it.getProperties().edit().setInteger("​s.iconColorFilter",​ 0x00ffffff).commit();​ 
-  it.setTag("​frozen",​true);​+  it.setTag("​frozen",​ true);
 } }
  
 function unfreezeEffect(it){ function unfreezeEffect(it){
-  it.getProperties().edit().setInteger("​s.iconColorFilter",​0xffffffff).commit();​ +  it.getProperties().edit().setInteger("​s.iconColorFilter",​ 0xffffffff).commit();​ 
-  it.setTag("​frozen",​false);​+  it.setTag("​frozen",​ false);
 } }
  
-function ​getFrozenItIds(c){ +function ​batchFreezeAction(items, action, callback){ 
-  var cId c.getId(); +  var frozenStateChecker,​ cmd, effect; 
-  if(!frozenItIdss[cId]) +  if(action ​=== "​freeze"​){ 
-    ​frozenItIdss[cId] = new TagArray(c, "frozenItIds"); +    frozenStateChecker = function(it){ return !isFrozen(it);​ }; 
-  return ​frozenItIdss[cId];+    cmd = "pm disable "; 
 +    effect = function(it){ freezeEffect(it); } 
 +  ​}else if(action === "​unfreeze"​){ 
 +    frozenStateChecker = function(it){ return isFrozen(it);​ }; 
 +    cmd = "pm enable "; 
 +    effect = function(it){ unfreezeEffect(it);​ } 
 +  } 
 + 
 +  var freezableItems = [] 
 +    , cmds = []; 
 + 
 +  items.forEach(function(it){ 
 +    ​if(frozenStateChecker(it)){ 
 +      freezeChecks(it,​ function(pkgName){ 
 +        freezableItems.push(it);​ 
 +        cmds.push(cmd + pkgName); 
 +      }, false); 
 +    } 
 +  }); 
 + 
 +  if(cmds.length !== 0){ 
 +    var counter = 0; 
 +    runCmd(cmds,​ true, true, function(){ 
 +      callback();​ 
 +    }, function(){ 
 +      effect(freezableItems[counter]); 
 +      counter++;​ 
 +    }); 
 +  } 
 +
 + 
 +function containerFreezeAction(c,​ effect){ 
 +  var cs screen.getAllContainersById(c.getId());​ 
 +  cs.forEach(function(c){ 
 +    var opener; 
 +    if((opener = c.getOpener()) && opener.getType() === "​Folder"​) 
 +      effect(opener);​ 
 +  }); 
 +
 + 
 +function freezeContainer(c){ 
 +  batchFreezeAction(c.getAllItems(), "freeze", function(){ 
 +    containerFreezeAction(c,​ freezeEffect); 
 +  }); 
 +
 + 
 +function unfreezeContainer(c){ 
 +  batchFreezeAction(c.getAllItems(),​ "​unfreeze",​ function(){ 
 +    containerFreezeAction(c,​ unfreezeEffect);​ 
 +  }); 
 +
 + 
 +function isFrozen(it){ 
 +  return ​it.getTag("​frozen"​) === '​true'​;
 } }
  
 function getFrozenApps(){ function getFrozenApps(){
-  if(!frozenApps){ +  if(typeof ​frozenApps ​=== '​undefined'​){ 
-    frozenApps = runAsRoot("pm list packages -d", false); +    frozenApps = []; 
-    ​for(var i=0;​i<​frozenApps.length;​i++){ +    var pkgs = runCmd("pm list packages -d", false, false); 
-      frozenApps[i] = frozenApps[i].split(":"​)[1];​ +    ​pkgs.forEach(function(pkg, ​i){ 
-    }+      frozenApps[i] = pkg.split(":"​)[1];​ 
 +    });
   }   }
   return frozenApps;   return frozenApps;
Line 226: Line 514:
   startNewBackgroundThread(function(){   startNewBackgroundThread(function(){
     var items = c.getItems();​     var items = c.getItems();​
-    for(var i = 0; i<​items.length;​ i++){+    for(var i = 0; i < items.length;​ i++){
       syncItem(items.getAt(i));​       syncItem(items.getAt(i));​
     }     }
Line 233: Line 521:
  
 function syncItem(it){ function syncItem(it){
-  var c = it.getParent() +  var frozenApps = getFrozenApps();​ 
-    , frozenItIds = getFrozenItIds(c) +  if(it.getType() ​=== "​Shortcut"​){
-    , frozenApps = getFrozenApps();​ +
-  if(it.getType()=="​Shortcut"​){+
     var pkgName = getPackageName(it);​     var pkgName = getPackageName(it);​
     if(pkgName && isFreezable(pkgName)){     if(pkgName && isFreezable(pkgName)){
-      var matched = false +      var isFrozen = it.getTag("​frozen"​) === 'true'
-        , isFrozen = it.getTag("​frozen"​)=="true"+      var matched ​= frozenApps.some(function(pkg){ 
-      ​for(var 0; j<frozenApps.length; j++){ +        ​return pkg === pkgName; 
-        ​if(pkgName==frozenApps[j])+      }); 
-          matched = true+      if(!isFrozen ​&& ​matched){ 
-          if(isFreezable(it) ​&& ​!isFrozen){ +        handleGUIEdit(function(){ 
-            handleGUIEdit(function(){ +          freezeEffect(it);​ 
-              freezeEffect(it);​ +        }); 
-            }+      }else if(isFrozen && ​!matched){
-            frozenItIds.push(it.getId()); +
-            frozenItIds.queueSave();​ +
-          } +
-        } +
-      } +
-      ​if(!matched ​&& isFrozen){+
         handleGUIEdit(function(){         handleGUIEdit(function(){
           unfreezeEffect(it);​           unfreezeEffect(it);​
-        }+        });
-        frozenItIds.remove(it.getId());​ +
-        frozenItIds.queueSave();+
       }       }
     }     }
Line 264: Line 542:
 } }
  
-function handleGUIEdit(func){ +if(typeof getEvent !== "​undefined"​){ 
-  ​if (Looper.getMainLooper().getThread() ​== Thread.currentThread()) { +  ​var c 
-    func(); +    ​, e getEvent() 
-  ​} else { +    ​, it = e.getItem() 
-    ​GUIHandler.post(func);​ +    ​, data e.getData(); 
-  } +  ​if(data){ 
-+    ​if(data === "​sync"​){ 
- +      ​if(e.getContainer()){ 
-function startNewBackgroundThread(func){ +        ​syncContainer(c); 
-  var thread ​new Thread(function(){ +      }else{ 
-    ​func(); +        throw new Error("Could not find a way to determine the container to syncRun the script from an item in the container or from the container itself or add the container id directly afrer '​sync'​."
-    ​if(threads[Thread.currentThread().getId()].prepared==true){ +      } 
-      Looper.myLooper().getQueue().addIdleHandler(function(){ +    }else if(data.substring(04) === "​sync"​){ 
-        Looper.myLooper().quitSafely(); +      var cId data.substring(4, data.length);​ 
-      }) +      ​c = screen.getContainerById(cId); 
-      Looper.loop();​ +      if(!c) throw new Error("Could not find container with id:" + cId);
-    } +
-  ​}) +
-  thread.setUncaughtExceptionHandler(function(th,​ ex){ +
-    ​handleGUIEdit(function(){ +
-      ​alert(ex.getMessage());​ +
-    }) +
-  }) +
-  threads[thread.getId()] ​{}; +
-  thread.start()+
-+
- +
-function getHandler(){ +
-  if (Looper.getMainLooper().getThread() == Thread.currentThread()) { +
-    return GUIHandler+
-  }else{ +
-    var threadId = Thread.currentThread().getId(); +
-    if(threads[threadId].prepared!=true){ +
-      ​Looper.prepare();​ +
-      threads[threadId].prepared = true; +
-    ​+
-    ​return new Handler();​ +
-  ​} +
-+
- +
-function TagArray(ob, name, manualSave){ +
-  this.push.apply(thisJSON.parse(ob.getTag(name)) || []); +
-  var me this; +
-  this.save ​function(){ +
-    ob.setTag(name,​ JSON.stringify(Array.prototype.slice.call(me)));​ +
-  } +
-  if(manualSave!=true) this.queueSave();​ +
-+
- +
-TagArray.prototype = new Array(); +
-TagArray.prototype.constructor = TagArray; +
-TagArray.prototype.saveQueued = false; +
- +
-TagArray.prototype.queueSave = function(){ +
-  ​if(!this.queueSaved){ +
-    getHandler().post(this.save) +
-    this.queueSaved = true; +
-  } +
-+
- +
-TagArray.prototype.remove = function(el){ +
-  ​var ind this.indexOf(el); +
-  if(ind != -1) +
-    this.splice(ind1); +
-  else +
-    return false; +
-+
- +
-TagArray.prototype.clear = function(){ +
-  this.length = 0; +
-+
- +
-if(data){ +
-  if(data.length ​== 4)+
-    var c; +
-    if(it){ +
-      ​syncContainer(it.getParent()); +
-    ​}else ​if(c = e.getContainer()){+
       syncContainer(c);​       syncContainer(c);​
-    }else{ 
-      throw new Error("​Could not find a way to determine the container to sync. Run the script from an item in the container or from the container itself or add the container id directly afrer '​sync'​."​) 
     }     }
-  }else if(data.substring(0,​4) == "​sync"​){ +  }else{ 
-    var cId = data.substring(4,​ data.length) +    if(!it){ 
-      , c = LL.getContainerById(cId);​ +      c = e.getContainer();​
-    ​if(!c)throw new Error("​Could not find container with id:"+ cId) +
-    syncContainer(c);​ +
-  } +
-}else{ +
-  ​if(!it){ +
-    ​var ​c = e.getContainer(+
-      , cIds = new TagArray(script,​ "​cIds",​ true); +
-    if(c){+
       cId = c.getId();       cId = c.getId();
-      if(c.getTag("​longTapFreeze"​)=="​true"​){ +      if(c.getTag("​longTapFreeze"​) ​=== "​true"​){ 
-        ​customConfirmDialog("Are you sure you want to uninstall?"​, function(){+        ​if(confirm("Are you sure you want to uninstall?"​)){
           uninstall(c);​           uninstall(c);​
-          cIds.remove(c.getId());​ 
-          cIds.save();​ 
           Toast.makeText(context,​ "​Uninstalled!",​ Toast.LENGTH_SHORT).show();​           Toast.makeText(context,​ "​Uninstalled!",​ Toast.LENGTH_SHORT).show();​
-        });+        }
       }else{       }else{
-        ​customConfirmDialog("Are you sure you want to install?"​, function(){ +        ​if(confirm("Are you sure you want to install?"​)){ 
-          ​cIds.push(c.getId());​ +          ​c.setTag("​longTapFreeze",​ true); 
-          c.setTag("​longTapFreeze"​,true); +          setEventHandlerRestorably(c, freezeEvent,​ EventHandler.RUN_SCRIPT,​ script.getId());​ 
-          ​loanEventHandler(c, freezeEvent, EventHandler.RUN_SCRIPT,​ script.getId());​ +          ​setEventHandlerRestorably(c, 'i.tap'EventHandler.RUN_SCRIPT,​ script.getId()); 
-          ​loanEventHandler(c, menuEvent, EventHandler.RUN_SCRIPT,​ script.getId());​ +          ​setEventHandlerRestorably(c, "​i.menu"​, EventHandler.RUN_SCRIPT,​ script.getId());​ 
-          ​customConfirmDialog("Do you want to enable autosync?"​, function(){ +          ​setEventHandlerRestorably(c, "​menu"​, EventHandler.RUN_SCRIPT,​ script.getId());​ 
-            ​loanEventHandler(c, "​resumed",​ EventHandler.RUN_SCRIPT,​ script.getId()+"​sync"​);​+          ​if(confirm("Do you want to enable autosync?"​)){ 
 +            ​setEventHandlerRestorably(c, "​resumed",​ EventHandler.RUN_SCRIPT,​ script.getId() + "/sync"); 
 +            syncContainer(c);
             c.setTag("​autosync",​ true);             c.setTag("​autosync",​ true);
-          }); +          }
-          cIds.save();​+
           Toast.makeText(context,​ "​Installed!",​ Toast.LENGTH_SHORT).show();​           Toast.makeText(context,​ "​Installed!",​ Toast.LENGTH_SHORT).show();​
-        });+        }
       }       }
     }else{     }else{
-      ​customConfirmDialog("​Are you sure you want to uninstall from every container?",​ function(){ +      var src = e.getSource();​ 
-        for(var i=0;​i<​cIds.length;​i++){ +      if(src ​=== freezeSource){ 
-          uninstall(LL.getContainerById(cIds[i]));​ +        if(isFrozen(it)){ 
-        } +          unfreeze(it);​
-        cIds.clear();​ +
-        cIds.save();​ +
-        Toast.makeText(context,​ "​Uninstalled everywhere!",​ Toast.LENGTH_SHORT).show();​ +
-      }); +
-    } +
-  } else { +
-    ​var src = e.getSource();​ +
-    if(src==freezeSource){ +
-      var c = it.getParent() +
-        ​, pkgName = getPackageName(it);​ +
-      ​if(isFreezable(pkgName)){ +
-        if(it.getTag("​frozen"​)=="​true"​){ +
-          unfreeze(it, pkgName);+
         }else{         }else{
-          freeze(it, pkgName);+          freeze(it);
         }         }
-      }else{ +      }else if(src === '​I_CLICK'​)
-        ​Toast.makeText(context, ​"Cannot freeze/unfreeze(Probably because of black- or whitelist"​Toast.LENGTH_SHORT).show();+        ​if( isFrozen(it) && confirm("Unfreeze and run?"​)) 
 +          ​unfreeze(itfunction(){ 
 +            it.launch()
 +          }); 
 +        else 
 +          it.launch();
       }       }
-    }else if(src == menuSource){ 
-      LL.bindClass("​android.R"​);​ 
-      LL.bindClass("​java.util.ArrayList"​);​ 
-      LL.bindClass("​android.view.ViewTreeObserver"​);​ 
-      LL.bindClass("​android.widget.Button"​);​ 
-      LL.bindClass("​android.view.View"​);​ 
-      LL.bindClass("​android.os.Build"​);​ 
- 
-      var pkg = context.getPackageName() 
-        , rsrc = context.getResources() 
-        , id = rsrc.getIdentifier("​bubble_content",​ "​id", ​ pkg) 
-        , menu = context.getWindow().getDecorView().findViewById(id) 
-        , menuRoot = menu.getParent() 
-        , version = Build.VERSION.SDK_INT;​ 
-      ​ 
-      function add(text,​onClickFunction,​first,​list){ 
-        var t=new Button(LL.getContext());​ 
-        if(version >= 16) t.setBackground(first.getBackground().mutate().getConstantState().newDrawable());​ 
-        else t.setBackgroundDrawable(first.getBackground().mutate().newDrawable());​ 
-        t.setTypeface(first.getTypeface());​ 
-        if(version >= 14) t.setAllCaps(false);​ 
-        t.setTextSize(0,​first.getTextSize());​ 
-        if(version >= 21) t.setFontFeatureSettings(first.getFontFeatureSettings());​ 
-        t.setGravity(first.getGravity());​ 
-        t.setText(text);​ 
-        t.setOnClickListener(new View.OnClickListener(){ 
-        onClick:​onClickFunction 
-        }); 
-        list.addView(t);​ 
-      } 
- 
-      var obs=menuRoot.getViewTreeObserver() 
-        , l=new ViewTreeObserver.OnGlobalLayoutListener(){ 
-        onGlobalLayout:​function(){ 
-          var list=menu 
-            , first=list.getChildAt(0);​ 
-          add("​Sync",​ function(){ 
-            syncItem(it);​ 
-          },first, list) 
-          obs.removeOnGlobalLayoutListener(l);​ 
-          return true; 
-        } 
-      }; 
- 
-      obs.addOnGlobalLayoutListener(l);​ 
-      LL.runAction(EventHandler.LAUNCHER_MENU);​ 
     }     }
 +  }
 +}else if(menu){
 +  var mode = menu.getMode();​
 +  if(mode === Menu.MODE_ITEM_SUBMENU_ACTION || mode === Menu.MODE_ITEM_NO_EM){
 +    menu.addMainItem("​Sync frozen-state",​ function(){
 +      syncItem(item);​
 +      menu.close();​
 +    });
 +  }else if(mode === Menu.MODE_CONTAINER_SUBMENU_ITEMS){
 +    menu.addMainItem("​Sync frozen-state",​ function(){
 +      syncContainer(container);​
 +      menu.close();​
 +    });
 +    menu.addMainItem("​Freeze all items",​ function(){
 +      freezeContainer(container);​
 +      menu.close();​
 +    });
 +    menu.addMainItem("​Unfreeze all items",​ function(){
 +      unfreezeContainer(container);​
 +      menu.close();​
 +    });
   }   }
 } }
 </​sxh>​ </​sxh>​
script_autosetupappfreeze.1472475028.txt.gz · Last modified: 2016/08/29 12:50 by cdfa