1543411337077true1646488154627114115ContextChanged30500%modes_contexts1485323611359true1590293383258130true137138Headphones-Example301544825256683true1629861081403144true143CheckForModesUpdate26165%modes_updatecheck2true1544301750876true1628065949892148true187ModesMediaOverride30500%VOLM1646488205355true16464882053558184115ContextCleared30600%Modes_Contexts1545541948475true16298616455185152MonitorStart5030701443816148810true157059026488455true5657Night-Example1469483841722Modes51,114,184,55,148,144,130175,115,187,52,113,180,138,154,60,9,83,202,186,18,143,112,56,201,39,34,82,192,140,137,181,57,20,13falseModes - A contextual settings framework to streamline the process of changing settings based on your current situation.
GitHub page with more details: https://github.com/jhotmann/tasker-phone-modes
false
Setup15431150594591637607784568112AddToContext100true129const par1 = local('par1');
const par2 = local('par2');
let context = global('Modes_Contexts').split(',').filter(c => c.length > 0);
if (par1) {
switch (par2) {
case ('if-not-exist'):
case ('if-not-exists'): {
if (context.indexOf(par1) === -1) appendToContext(par1);
break;
}
case (par2.match(/^max-count=\d+$/) || {}).input: {
let maxCount = parseInt(par2.toLowerCase().replace('max-count=', ''));
if (maxCount) {
let currentCount = context.filter((c) => { return c === par1; }).length;
if (currentCount < maxCount) appendToContext(par1);
}
break;
}
default: { appendToContext(par1); }
}
}
function appendToContext(c) {
context.push(c);
setGlobal('Modes_Contexts', context.join(','));
}%par112mw_av_playlist_add15431150594591646488127512113RemoveFromContext100true129const par1 = local('par1');
const par2 = local('par2') || '';
let context = global('Modes_Contexts').split(',').filter(c => c.length > 0);
let index = context.indexOf(par1);
if (index > -1) {
if (par2.toLowerCase() === 'all') { // remove all occurances
while (index > -1) {
context.splice(index, 1);
index = context.indexOf(par1);
}
setGlobal('Modes_Contexts', context.join(','));
} else { // remove first occurance
context.splice(index, 1);
setGlobal('Modes_Contexts', context.join(','));
}
}%par112mw_av_playlist_play15434113456251646870976978115ContextChanged1002true30129let version = '1.9.0';
setGlobal('Modes_Version', version);
const ALL_CONFIGS = JSON.parse(global('Modes_Configs'));
const DEFAULT_CONTEXT = global('Modes_DefaultContext');
let contexts = global('Modes_Contexts').split(',').filter(c => { return (c !== '') });
let previousContexts = global('Modes_ActiveContexts').split(',').filter(c => { return (c !== '') });
// Filter down to only configs in %Modes_Contexts
let configs = ALL_CONFIGS.filter(c => { return contexts.indexOf(c.name) > -1 });
let defaultContext = (DEFAULT_CONTEXT && typeof DEFAULT_CONTEXT === 'string' ? ALL_CONFIGS.find(c => { return c.name === DEFAULT_CONTEXT }) : null) || { priority: 0 };
// Determine which contexts will be activated based upon type and priority
let activeContexts = [];
let primaryContext = configs.filter(c => { return c.type === 1; }).sort((a, b) => { return a.priority - b.priority; }).pop() || defaultContext;
let primaryPriority = primaryContext.priority || 0;
activeContexts.push(primaryContext.name);
let secondaryContexts = configs.filter(c => { return (c.type === 2 && c.priority >= primaryPriority); }).sort((a, b) => { return a.priority - b.priority; });
secondaryContexts.forEach(c => {
activeContexts.push(c.name);
});
// Determine which contexts are newly active and inactive
let newContexts = missingItems(activeContexts, previousContexts);
let inactivatedContexts = missingItems(previousContexts, activeContexts);
// Perform exit parameters for inactivated contexts
ALL_CONFIGS
.filter(c => { return inactivatedContexts.indexOf(c.name) > -1 })
.forEach(context => {
if (context.exit) {
if (context.exit.profilesToDisable && Array.isArray(context.exit.profilesToDisable)) context.exit.profilesToDisable.forEach(prof => { changeProfileStatus(prof, false); });
if (context.exit.profilesToEnable && Array.isArray(context.exit.profilesToEnable)) context.exit.profilesToEnable.forEach(prof => { changeProfileStatus(prof, true); });
if (context.exit.tasksToRun && Array.isArray(context.exit.tasksToRun)) context.exit.tasksToRun.forEach(tsk => {
if (typeof tsk === 'string') {
executeTask(tsk, 10, null, null);
} else if (typeof tsk === 'object' && tsk.name) {
executeTask(tsk.name, tsk.priority, tsk.param1, tsk.param2);
}
});
}
});
// Merge active context's settings
let merged = {};
if (primaryContext) {
Object.keys(primaryContext).forEach(key => {
if (['name', 'type', 'priority', 'enter', 'exit'].indexOf(key) === -1 && primaryContext[key] !== null) merged[key] = primaryContext[key];
});
}
secondaryContexts.forEach(context => {
Object.keys(context).forEach(key => {
if (['name', 'type', 'priority', 'enter', 'exit'].indexOf(key) === -1 && context[key] !== null) merged[key] = context[key];
});
});
// Change settings according to merged context
// DND first, if going from none/priority to all it must occur for media volume changes to occur (Android 12+)
if (existsIsType(merged, 'dnd', 'string')) performTask('DoNotDisturb', 10, merged.dnd, '');
// Only change media volume if %Modes_MediaOverride != 1
const mediaVolExists = existsIsType(merged, 'volume_media', 'int');
if (existsIsType(merged, 'volume_media_override', 'boolean') && merged.volume_media_override) {
if (mediaVolExists && global('Modes_MediaOverride') !== '1') mediaVol(merged.volume_media, false, false);
enableProfile('ModesMediaOverride', true);
} else {
enableProfile('ModesMediaOverride', false);
setGlobal('Modes_MediaOverride', '0');
if (mediaVolExists) mediaVol(merged.volume_media, false, false);
}
if (existsIsType(merged, 'volume_notification', 'int')) notificationVol(merged.volume_notification, false, false);
if (existsIsType(merged, 'location', 'string')) performTask('LocationMode', 10, merged.location, '');
if (existsIsType(merged, 'wifiOn', 'boolean')) setWifi(merged.wifiOn);
if (existsIsType(merged, 'bluetoothOn', 'boolean')) setBT(merged.bluetoothOn);
if (existsIsType(merged, 'mobileDataOn', 'boolean')) performTask('MobileData', 10, merged.mobileDataOn, '');
if (existsIsType(merged, 'airplaneModeOn', 'boolean')) setAirplaneMode(merged.airplaneModeOn);
if (existsIsType(merged, 'screenRotationOn', 'boolean')) performTask('DisplayRotate', 10, merged.screenRotationOn, '');
if (existsIsType(merged, 'displayTimeout', 'int')) displayTimeout(0, merged.displayTimeout, 0);
if (existsIsType(merged, 'displayBrightness', 'int') || existsIsType(merged, 'displayBrightness', 'string')) performTask('DisplayBrightness', 10, merged.displayBrightness, '');
if (existsIsType(merged, 'nightLightOn', 'boolean')) performTask('NightLight', 10, merged.nightLightOn, '');
if (existsIsType(merged, 'extraDimOn', 'boolean')) performTask('ExtraDim', 10, merged.extraDimOn, '');
if (existsIsType(merged, 'immersiveMode', 'string')) performTask('ImmersiveMode', 10, merged.immersiveMode, '');
if (existsIsType(merged, 'darkMode', 'boolean')) performTask('DarkMode', 10, merged.darkMode, '');
if (existsIsType(merged, 'grayscaleMode', 'boolean')) performTask('GrayscaleMode', 10, merged.grayscaleMode, '');
if (existsIsType(merged, 'hapticFeedbackOn', 'boolean')) performTask('TouchVibrations', 10, merged.hapticFeedbackOn, '');
if (existsIsType(merged, 'batterySaverOn', 'boolean')) performTask('BatterySaver', 10, merged.batterySaverOn, '');
if (existsIsType(merged, 'owntracksMode', 'int')) performTask("OwntracksMode", 10, merged.owntracksMode, '');
if (existsIsType(merged, 'owntracksMode', 'string')) performTask("OwntracksMode", 10, owntracksStringToInt(merged.owntracksMode), '');
// Perform enter parameters for new contexts
ALL_CONFIGS
.filter(context => { return (newContexts.indexOf(context.name) > -1) })
.forEach(context => {
if (context.enter) {
if (context.enter.profilesToDisable && Array.isArray(context.enter.profilesToDisable)) context.enter.profilesToDisable.forEach(prof => { changeProfileStatus(prof, false); });
if (context.enter.profilesToEnable && Array.isArray(context.enter.profilesToEnable)) context.enter.profilesToEnable.forEach(prof => { changeProfileStatus(prof, true); });
if (context.enter.tasksToRun && Array.isArray(context.enter.tasksToRun)) context.enter.tasksToRun.forEach(tsk => {
if (typeof tsk === 'string') {
executeTask(tsk, 10, null, null);
} else if (typeof tsk === 'object' && tsk.name) {
executeTask(tsk.name, tsk.priority, tsk.param1, tsk.param2);
}
});
}
});
setGlobal('Modes_ActiveContexts', activeContexts.join(','));
setLocal('active', activeContexts.join(', ') || DEFAULT_CONTEXT);
exit();
// Helper functions
function missingItems(arr1, arr2) {
var missing = arr1.filter(function(item) {
return arr2.indexOf(item) === -1;
});
return missing;
}
function existsIsType(obj, key, type) {
if (Object.keys(obj).indexOf(key) === -1) return false;
if (type === 'int') return (Number.isInteger(obj[key]));
else return (typeof obj[key] === type);
}
function changeProfileStatus(name, on) {
enableProfile(name, on);
wait(1000);
}
function executeTask(name, priority, param1, param2) {
performTask(name, priority, param1, param2);
wait(500);
}
function owntracksStringToInt(mode) {
switch (mode.toLowerCase()) {
case 'quiet':
return -1;
case 'manual':
return 0;
case 'move':
return 2;
default:
return 1;
}
}120548%active#FFFFFFFFTopℹ️ Context Changed#BF606060EditContext4000%SCREEN2onmw_image_photo_filter1469555817040154473650988013DisplayRotate596%par1%rotate%par112822Or%rotate4true|on%par113822%rotate4false|offmw_device_screen_rotation14853236162431590293377013137130AddToContext%priorityearbuds15434222753951590293383258138130RemoveFromContext%priorityearbuds130RemoveFromContext%prioritymediaoverrideall15444539720071621575081741140BatterySaver100596%par1%par112175Or%par14false|off%par113175%par14true|onmw_device_battery_alert15448224593441572403451994143CheckForModesUpdate100339<StringArray sr=""><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0>%http_data
Data
Data that the server responded from the HTTP request.</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1>%http_response_code
Response Code
The HTTP Code the server responded</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2>%http_headers()
Response Headers
The HTTP Headers the server sent in the response. Each header is in the 'key:value' format</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3>%http_response_length
Response Length
The size of the response in bytes</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3></StringArray>[Ljava.lang.String;https://github.com/jhotmann/tasker-phone-modes/releases.atom598%http_data(?<=title>)\d+\.\d+\.\d+%versions43AndAnd%versions137%currentversion3%versions128%currentversion2%versions118%currentversion1135NotifyUpdate4313738523Modes Update AvailableSelect UPDATE to launch Taskernetmodes_updatesmw_notification_system_update104https://taskernet.com/shares/?user=AS35m8k7601Z2ol5UAzuT033Ll5H1yhruZrDvDITEN2l4b5o%2Fm1AF9Dpj3WrfO36Pgh2&id=Project%3AModes137%versions113590%versions1.547%currentversion%Modes_Version590%currentversion.37%versions117%currentversion1135NotifyUpdate43And%versions127%currentversion2%versions118%currentversion1135NotifyUpdatemw_notification_system_update15728300364521646871493540154ReadConfigFiles1001129const CONFIG_PATH = global('Modes_ConfigPath');
let configs = [];
let fileList = listFiles(CONFIG_PATH).split('\n').filter(f => { return (f !== '') });
fileList.forEach(f => {
let conf = readConfigFile(f);
configs.push(conf);
});
setGlobal('Modes_Configs', JSON.stringify(configs));
exit();
function readConfigFile(configName) {
let configText = '{}';
try {
configText = readFile(configName);
} catch (error) {
flash('Error reading configuration file ' + configName);
}
let conf = JSON.parse(configText);
if (!conf.name) conf.name = configName.replace(/^.*\/|\.[A-Za-z]+$/g, '');
if (!conf.type) conf.type = 1;
if (!conf.priority) conf.priority = 50;
// Translate old configuration format
if (Object.keys(conf).indexOf('volume') > -1) {
if (conf.volume.media !== null) conf.volume_media = conf.volume.media;
if (conf.volume.notification !== null) conf.volume_notification = conf.volume.notification;
if (conf.volume.dnd !== null) conf.dnd = conf.volume.dnd;
delete conf.volume;
}
return conf;
}mw_editor_format_line_spacing15722090348761637607936585175EditContext1001512false360<StringArray sr=""><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0>%input
Input
The text that was inserted in the dialog</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0></StringArray>[Ljava.lang.String;Edit ContextA comma-separtated lists of contexts%Modes_Contexts524289547%Modes_Contexts%inputmw_editor_border_color1543968812849162986150487018ConfigCreator100true104https://rawgit.com/jhotmann/tasker-phone-modes/master/ConfigCreator/ConfigCreator.htmlmw_action_note_add14694650530411575825633571180ImmersiveMode596%par1%mode%par112906Or%par12off%par113906%par12status906%par12navigation906%par14both|fullmw_navigation_fullscreen15444539720071646720889824181DarkMode100596%par1%par112361<StringArray sr=""><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0>%new_state
New State
true if it after the action the setting is enabled, false if not</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0></StringArray>[Ljava.lang.String;%par14true|on361<StringArray sr=""><_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0>%new_state
New State
true if it after the action the setting is enabled, false if not</_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0></StringArray>[Ljava.lang.String;%par14false|offmw_action_invert_colors16467204734811646720796001186NightLight596%par1%par112235night_display_activated1%par14true|on|1235night_display_activated0Or%par14false|off|0%par113mw_image_brightness_31544301755191162806594989218761547%Modes_MediaOverride116215750090221646720625423192ExtraDim100596%par1%par112235reduce_bright_colors_activated1%par14true|on|1235reduce_bright_colors_activated0Or%par14off|false|0%par113mw_image_brightness_31471285453782162986147816420Setup100129var configPath = global('%Modes_ConfigPath');
var path = prompt('What folder will contain your config files? (No trailing slash)', (configPath ? configPath : '/sdcard/Tasker/ModeConfigs'));
if (path != null) {
setGlobal('Modes_ConfigPath', path);
}409false%Modes_ConfigPath129performTask('ReadConfigFiles', 99, null, null);
var defaultContext = global('Modes_DefaultContext');
var dc = prompt('What would you like to be the default primary context?', (defaultContext ? defaultContext : ''));
if (dc != null) {
setGlobal('Modes_DefaultContext', dc);
}
var cfu = confirm('Would you like to periodically check for project updates?');
enableProfile('CheckForModesUpdate', cfu);
enableProfile('ContextChanged', true);
enableProfile('MonitorStart', true);130falseReadConfigFiles%priority+1159falseContextChanged159falseCheckForModesUpdate159falseMonitorStartmw_communication_phonelink_setup15192502137201628478108259201GrayscaleMode100547%par1off%par113596%par1235accessibility_display_daltonizer_enabled1%par14true|on235accessibility_display_daltonizer_enabled0%par14false|offmw_image_tonality16298602230411646720852472202ModesTest100548%modes_contextsmw_editor_text_fields1452598211627162157505809134TouchVibrations100596%par1%par112235haptic_feedback_enabled1Or%par14true|on%par113235haptic_feedback_enabled0%par14false|offmw_action_touch_app1469465053041157582594197239LocationMode100596%par1%mode%par112905Or%par113%par12accuracy905%par12off905%par12battery905%par12devicemw_maps_my_location154554195396616298616455185251130ReadConfigFiles%priority+1549%modes_contexts1443816152178157059026488456100130AddToContext%prioritynight%Modes_Contexts5(^|,)night($|,)1543421571650154404841147257100130RemoveFromContext%prioritynight1638022399682164686355486260OwntracksMode547%par11%par113877org.owntracks.android.CHANGE_MONITORINGmonitoring:%par1mw_maps_pin_drop1544039715157160102995062882DisplayBrightness100596%par1%par112808Or%par12auto%par113808%par14^\d+$810%par1%par14^\d+$mw_image_brightness_61544453972007157604546567983MobileData100596%par1%par112433Or%par12false%par12off433Or%par12true%par12onmw_device_signal_cellular_3_bar146946505304115872998827449DoNotDisturb596%par1%mode%par112312Or%mode2all%par113312%mode2priority312%mode2alarms312%mode2nonemw_notification_do_not_disturb_off