forked from jens/Automation
profile trigger
This commit is contained in:
parent
5653a9c70e
commit
941bb3e1af
@ -12,7 +12,6 @@ import android.widget.Toast;
|
|||||||
import com.google.android.gms.location.DetectedActivity;
|
import com.google.android.gms.location.DetectedActivity;
|
||||||
import com.jens.automation2.receivers.ActivityDetectionReceiver;
|
import com.jens.automation2.receivers.ActivityDetectionReceiver;
|
||||||
|
|
||||||
import java.sql.Time;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -835,7 +834,31 @@ public class Rule implements Comparable<Rule>
|
|||||||
return ruleCandidates;
|
return ruleCandidates;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public static ArrayList<Rule> findRuleCandidatesByProfile(Profile profile)
|
public static ArrayList<Rule> findRuleCandidatesByTriggerProfile(Profile profile)
|
||||||
|
{
|
||||||
|
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
|
||||||
|
|
||||||
|
for(Rule oneRule : ruleCollection)
|
||||||
|
{
|
||||||
|
innerloop:
|
||||||
|
for(Trigger oneTrigger : oneRule.getTriggerSet())
|
||||||
|
{
|
||||||
|
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.profileActive)
|
||||||
|
{
|
||||||
|
String profileName = oneTrigger.getTriggerParameter2().split(triggerParameter2Split)[0];
|
||||||
|
if(profileName.equals(profile.getName()))
|
||||||
|
{
|
||||||
|
ruleCandidates.add(oneRule);
|
||||||
|
break innerloop; //if the profile is found we don't need to search the other triggers in the same rule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ruleCandidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<Rule> findRuleCandidatesByActionProfile(Profile profile)
|
||||||
{
|
{
|
||||||
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
|
ArrayList<Rule> ruleCandidates = new ArrayList<Rule>();
|
||||||
|
|
||||||
|
@ -184,8 +184,16 @@ public class ActivityMainProfiles extends ActivityGeneric
|
|||||||
startActivityForResult(manageSpecificProfileIntent, 2000);
|
startActivityForResult(manageSpecificProfileIntent, 2000);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if(profile.delete(myAutomationService))
|
Rule user = profile.isInUseByRules();
|
||||||
|
if(user == null)
|
||||||
|
{
|
||||||
|
if (profile.delete(ActivityMainProfiles.this))
|
||||||
updateListView();
|
updateListView();
|
||||||
|
else
|
||||||
|
Toast.makeText(ActivityMainProfiles.this, getResources().getString(R.string.profileCouldNotBeDeleted), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Toast.makeText(ActivityMainProfiles.this, String.format(getResources().getString(R.string.ruleXIsUsingProfileY), user.getName(), profile.getName()), Toast.LENGTH_LONG).show();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,12 +608,20 @@ public class ActivityManageRule extends Activity
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if(triggerType == Trigger_Enum.profileActive)
|
else if(triggerType == Trigger_Enum.profileActive)
|
||||||
|
{
|
||||||
|
if(Profile.getProfileCollection().size() > 0)
|
||||||
{
|
{
|
||||||
newTrigger.setTriggerType(Trigger_Enum.profileActive);
|
newTrigger.setTriggerType(Trigger_Enum.profileActive);
|
||||||
Intent profileTriggerEditor = new Intent(myContext, ActivityManageTriggerProfile.class);
|
Intent profileTriggerEditor = new Intent(myContext, ActivityManageTriggerProfile.class);
|
||||||
startActivityForResult(profileTriggerEditor, requestCodeTriggerProfileAdd);
|
startActivityForResult(profileTriggerEditor, requestCodeTriggerProfileAdd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Toast.makeText(context, getResources().getString(R.string.noProfilesCreateOneFirst), Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(triggerType == Trigger_Enum.activityDetection)
|
else if(triggerType == Trigger_Enum.activityDetection)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -43,7 +43,7 @@ public class ActivityManageTriggerDeviceOrientation extends Activity
|
|||||||
{
|
{
|
||||||
desiredAzimuth = Float.parseFloat(etDesiredAzimuth.getText().toString());
|
desiredAzimuth = Float.parseFloat(etDesiredAzimuth.getText().toString());
|
||||||
desiredAzimuthTolerance = Float.parseFloat(etDesiredAzimuthTolerance.getText().toString());
|
desiredAzimuthTolerance = Float.parseFloat(etDesiredAzimuthTolerance.getText().toString());
|
||||||
if (Math.abs(azimuth) <= Math.abs(desiredAzimuth - desiredAzimuthTolerance) || Math.abs(azimuth) <= desiredAzimuth + desiredAzimuthTolerance)
|
if (desiredAzimuthTolerance == 180 || (desiredAzimuth - desiredAzimuthTolerance <= azimuth && azimuth <= desiredAzimuth + desiredAzimuthTolerance))
|
||||||
{
|
{
|
||||||
tvAppliesAzimuth.setText(getResources().getString(R.string.yes));
|
tvAppliesAzimuth.setText(getResources().getString(R.string.yes));
|
||||||
tvAppliesAzimuth.setTextColor(Color.GREEN);
|
tvAppliesAzimuth.setTextColor(Color.GREEN);
|
||||||
@ -63,7 +63,7 @@ public class ActivityManageTriggerDeviceOrientation extends Activity
|
|||||||
{
|
{
|
||||||
desiredPitch = Float.parseFloat(etDesiredPitch.getText().toString());
|
desiredPitch = Float.parseFloat(etDesiredPitch.getText().toString());
|
||||||
desiredPitchTolerance = Float.parseFloat(etDesiredPitchTolerance.getText().toString());
|
desiredPitchTolerance = Float.parseFloat(etDesiredPitchTolerance.getText().toString());
|
||||||
if (Math.abs(pitch) <= Math.abs(desiredPitch - desiredPitchTolerance) || Math.abs(pitch) <= desiredPitch + desiredPitchTolerance)
|
if (desiredPitchTolerance == 180 || (desiredPitch - desiredPitchTolerance <= pitch && pitch <= desiredPitch + desiredPitchTolerance))
|
||||||
{
|
{
|
||||||
tvAppliesPitch.setText(getResources().getString(R.string.yes));
|
tvAppliesPitch.setText(getResources().getString(R.string.yes));
|
||||||
tvAppliesPitch.setTextColor(Color.GREEN);
|
tvAppliesPitch.setTextColor(Color.GREEN);
|
||||||
@ -83,7 +83,7 @@ public class ActivityManageTriggerDeviceOrientation extends Activity
|
|||||||
{
|
{
|
||||||
desiredRoll = Float.parseFloat(etDesiredRoll.getText().toString());
|
desiredRoll = Float.parseFloat(etDesiredRoll.getText().toString());
|
||||||
desiredRollTolerance = Float.parseFloat(etDesiredRollTolerance.getText().toString());
|
desiredRollTolerance = Float.parseFloat(etDesiredRollTolerance.getText().toString());
|
||||||
if (Math.abs(roll) <= Math.abs(desiredRoll - desiredRollTolerance) || Math.abs(roll) <= desiredRoll + desiredRollTolerance)
|
if (desiredRollTolerance == 180 || (desiredRoll - desiredRollTolerance <= roll && roll <= desiredRoll + desiredRollTolerance))
|
||||||
{
|
{
|
||||||
tvAppliesRoll.setText(getResources().getString(R.string.yes));
|
tvAppliesRoll.setText(getResources().getString(R.string.yes));
|
||||||
tvAppliesRoll.setTextColor(Color.GREEN);
|
tvAppliesRoll.setTextColor(Color.GREEN);
|
||||||
@ -159,14 +159,16 @@ public class ActivityManageTriggerDeviceOrientation extends Activity
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v)
|
public void onClick(View v)
|
||||||
{
|
{
|
||||||
|
// Round the values. Too long decimals will destroy the layout
|
||||||
|
|
||||||
if(!StringUtils.isEmpty(currentAzimuth.getText()))
|
if(!StringUtils.isEmpty(currentAzimuth.getText()))
|
||||||
etDesiredAzimuth.setText(currentAzimuth.getText());
|
etDesiredAzimuth.setText(String.valueOf(Math.round(Float.parseFloat(currentAzimuth.getText().toString()))));
|
||||||
|
|
||||||
if(!StringUtils.isEmpty(currentPitch.getText()))
|
if(!StringUtils.isEmpty(currentPitch.getText()))
|
||||||
etDesiredPitch.setText(currentPitch.getText());
|
etDesiredPitch.setText(String.valueOf(Math.round(Float.parseFloat(currentPitch.getText().toString()))));
|
||||||
|
|
||||||
if(!StringUtils.isEmpty(currentRoll.getText()))
|
if(!StringUtils.isEmpty(currentRoll.getText()))
|
||||||
etDesiredRoll.setText(currentRoll.getText());
|
etDesiredRoll.setText(String.valueOf(Math.round(Float.parseFloat(currentRoll.getText().toString()))));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -216,6 +216,14 @@ public class Miscellaneous extends Service
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int boolToInt(boolean input)
|
||||||
|
{
|
||||||
|
if(input)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent arg0)
|
public IBinder onBind(Intent arg0)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.jens.automation2;
|
package com.jens.automation2;
|
||||||
|
|
||||||
|
import android.app.NotificationManager;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
@ -291,17 +292,11 @@ public class Profile implements Comparable<Profile>
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean delete(AutomationService myAutomationService)
|
|
||||||
{
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean applyRingTone(File ringtoneFile, int ringtoneType, Context context)
|
private boolean applyRingTone(File ringtoneFile, int ringtoneType, Context context)
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "Profile", "Request to set ringtone to " + ringtoneFile.getAbsolutePath(), 3);
|
Miscellaneous.logEvent("i", "Profile", "Request to set ringtone to " + ringtoneFile.getAbsolutePath(), 3);
|
||||||
|
|
||||||
if(!ringtoneFile.exists() | !ringtoneFile.canRead())
|
if(!ringtoneFile.exists() || !ringtoneFile.canRead())
|
||||||
{
|
{
|
||||||
String message = "Ringtone file does not exist or cannot read it: " + ringtoneFile.getAbsolutePath();
|
String message = "Ringtone file does not exist or cannot read it: " + ringtoneFile.getAbsolutePath();
|
||||||
Miscellaneous.logEvent("i", "Profile", message, 3);
|
Miscellaneous.logEvent("i", "Profile", message, 3);
|
||||||
@ -392,7 +387,7 @@ public class Profile implements Comparable<Profile>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if rules reference this profile
|
// Check if rules reference this profile
|
||||||
ArrayList<Rule> rulesThatReferenceMe = Rule.findRuleCandidatesByProfile(this);
|
ArrayList<Rule> rulesThatReferenceMe = Rule.findRuleCandidatesByActionProfile(this);
|
||||||
if(rulesThatReferenceMe.size() > 0)
|
if(rulesThatReferenceMe.size() > 0)
|
||||||
{
|
{
|
||||||
for(Rule oneRule : rulesThatReferenceMe)
|
for(Rule oneRule : rulesThatReferenceMe)
|
||||||
@ -402,7 +397,7 @@ public class Profile implements Comparable<Profile>
|
|||||||
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.profileActive)
|
if(oneTrigger.getTriggerType() == Trigger.Trigger_Enum.profileActive)
|
||||||
{
|
{
|
||||||
String[] parts = oneTrigger.getTriggerParameter2().split(Trigger.triggerParameter2Split);
|
String[] parts = oneTrigger.getTriggerParameter2().split(Trigger.triggerParameter2Split);
|
||||||
parts[1] = this.name;
|
parts[0] = this.name;
|
||||||
|
|
||||||
oneTrigger.setTriggerParameter2(Miscellaneous.explode(Trigger.triggerParameter2Split, parts));
|
oneTrigger.setTriggerParameter2(Miscellaneous.explode(Trigger.triggerParameter2Split, parts));
|
||||||
// We don't need to save the file. This will happen anyway in PointOfInterest.writePoisToFile() below.
|
// We don't need to save the file. This will happen anyway in PointOfInterest.writePoisToFile() below.
|
||||||
@ -437,18 +432,49 @@ public class Profile implements Comparable<Profile>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean delete()
|
public Rule isInUseByRules()
|
||||||
{
|
{
|
||||||
for(int i = 0; i< Profile.getProfileCollection().size(); i++)
|
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.profileActive))
|
||||||
{
|
{
|
||||||
if(Profile.getProfileCollection().get(i).getName().equals(this.getName()))
|
for (Rule rule : Rule.findRuleCandidatesByTriggerProfile(this))
|
||||||
{
|
{
|
||||||
Profile.getProfileCollection().remove(0);
|
return rule;
|
||||||
|
|
||||||
// write to file
|
|
||||||
return XmlFileInterface.writeFile();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(Rule.isAnyRuleUsing(Action_Enum.changeSoundProfile))
|
||||||
|
{
|
||||||
|
for (Rule rule : Rule.findRuleCandidatesByActionProfile(this))
|
||||||
|
{
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean delete(Context context)
|
||||||
|
{
|
||||||
|
if(Rule.isAnyRuleUsing(Trigger.Trigger_Enum.profileActive))
|
||||||
|
{
|
||||||
|
for (Rule rule : Rule.findRuleCandidatesByTriggerProfile(this))
|
||||||
|
{
|
||||||
|
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), rule.getName(), this.getName()), Toast.LENGTH_LONG).show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Rule.isAnyRuleUsing(Action_Enum.changeSoundProfile))
|
||||||
|
{
|
||||||
|
for (Rule rule : Rule.findRuleCandidatesByActionProfile(this))
|
||||||
|
{
|
||||||
|
Toast.makeText(context, String.format(context.getResources().getString(R.string.ruleXIsUsingProfileY), rule.getName(), this.getName()), Toast.LENGTH_LONG).show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
profileCollection.remove(this);
|
||||||
|
return XmlFileInterface.writeFile();
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -557,6 +583,104 @@ public class Profile implements Comparable<Profile>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean areMySettingsCurrentlyActive(Context context)
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("i", "Profile " + this.getName(), "Checking if profile's settings are currently active.", 3);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AudioManager am = (AudioManager) Miscellaneous.getAnyContext().getSystemService(Context.AUDIO_SERVICE);
|
||||||
|
NotificationManager mNotificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
|
if(changeSoundMode)
|
||||||
|
{
|
||||||
|
if(am.getRingerMode() != soundMode)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(changeDndMode && Build.VERSION.SDK_INT >= 23)
|
||||||
|
{
|
||||||
|
if(mNotificationManager.getCurrentInterruptionFilter() != dndMode)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(changeVolumeMusicVideoGameMedia)
|
||||||
|
{
|
||||||
|
if(am.getStreamVolume(AudioManager.STREAM_MUSIC) != volumeMusic)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(changeVolumeNotifications)
|
||||||
|
{
|
||||||
|
if(am.getStreamVolume(AudioManager.STREAM_NOTIFICATION) != volumeNotifications)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(changeVolumeAlarms)
|
||||||
|
{
|
||||||
|
if(am.getStreamVolume(AudioManager.STREAM_ALARM) != volumeAlarms)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(changeIncomingCallsRingtone)
|
||||||
|
// {
|
||||||
|
// if (incomingCallsRingtone != null)
|
||||||
|
// {
|
||||||
|
// applyRingTone(incomingCallsRingtone, RingtoneManager.TYPE_RINGTONE, context);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
if(changeVibrateWhenRinging)
|
||||||
|
{
|
||||||
|
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
{
|
||||||
|
int currentSetting = android.provider.Settings.System.getInt(context.getContentResolver(), "vibrate_when_ringing");
|
||||||
|
if(currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int currentSetting = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
|
||||||
|
if(currentSetting != Miscellaneous.boolToInt(vibrateWhenRinging))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(changeNotificationRingtone)
|
||||||
|
// if(notificationRingtone != null)
|
||||||
|
// applyRingTone(notificationRingtone, RingtoneManager.TYPE_NOTIFICATION, context);
|
||||||
|
|
||||||
|
if(changeScreenLockUnlockSound)
|
||||||
|
{
|
||||||
|
int currentSetting = android.provider.Settings.System.getInt(context.getContentResolver(), "lockscreen_sounds_enabled");
|
||||||
|
if(currentSetting != Miscellaneous.boolToInt(screenLockUnlockSound))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(changeAudibleSelection)
|
||||||
|
{
|
||||||
|
int currentSetting = android.provider.Settings.System.getInt(context.getContentResolver(), android.provider.Settings.System.SOUND_EFFECTS_ENABLED);
|
||||||
|
if(currentSetting != Miscellaneous.boolToInt(audibleSelection))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(changeHapticFeedback)
|
||||||
|
{
|
||||||
|
int currentSetting = android.provider.Settings.System.getInt(context.getContentResolver(), android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED);
|
||||||
|
if(currentSetting != Miscellaneous.boolToInt(hapticFeedback))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Miscellaneous.logEvent("e", "Profile " + this.getName(), "Error while checking if profile settings are currently active. " + Log.getStackTraceString(e), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Miscellaneous.logEvent("i", "Profile " + this.getName(), "This profile's settings are currently active.", 4);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
@ -278,13 +278,22 @@ public class Trigger
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean checkProfileActive()
|
boolean checkProfileActive()
|
||||||
|
{
|
||||||
|
String demandedProfileName = getTriggerParameter2().split(Trigger.triggerParameter2Split)[0];
|
||||||
|
boolean checkSettings = Boolean.parseBoolean(getTriggerParameter2().split(Trigger.triggerParameter2Split)[1]);
|
||||||
|
|
||||||
|
if(checkSettings)
|
||||||
|
{
|
||||||
|
Profile profile = Profile.getByName(demandedProfileName);
|
||||||
|
return profile.areMySettingsCurrentlyActive(Miscellaneous.getAnyContext());
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String demandedProfileName = getTriggerParameter2().split(Trigger.triggerParameter2Split)[0];
|
|
||||||
Profile lastProfile = null;
|
Profile lastProfile = null;
|
||||||
|
|
||||||
if(Profile.profileActivationHistory.size() > 0)
|
if (Profile.profileActivationHistory.size() > 0)
|
||||||
{
|
{
|
||||||
lastProfile = Profile.profileActivationHistory.get(Profile.profileActivationHistory.size() - 1);
|
lastProfile = Profile.profileActivationHistory.get(Profile.profileActivationHistory.size() - 1);
|
||||||
|
|
||||||
@ -296,15 +305,15 @@ public class Trigger
|
|||||||
else
|
else
|
||||||
return !getTriggerParameter();
|
return !getTriggerParameter();
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("w", "Trigger", "Error checking profile trigger.", 4);
|
Miscellaneous.logEvent("w", "Trigger", "Error checking profile trigger.", 4);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean checkDeviceOrientation()
|
boolean checkDeviceOrientation()
|
||||||
{
|
{
|
||||||
String deviceOrientationPieces[] = getTriggerParameter2().split(Trigger.triggerParameter2Split);
|
String deviceOrientationPieces[] = getTriggerParameter2().split(Trigger.triggerParameter2Split);
|
||||||
@ -320,13 +329,7 @@ public class Trigger
|
|||||||
|
|
||||||
if(desiredAzimuthTolerance < 180)
|
if(desiredAzimuthTolerance < 180)
|
||||||
{
|
{
|
||||||
if (
|
if (!(desiredAzimuth - desiredAzimuthTolerance <= currentAzimuth && currentAzimuth <= desiredAzimuth + desiredAzimuthTolerance))
|
||||||
!(
|
|
||||||
Math.abs(currentAzimuth) <= Math.abs(desiredAzimuth - desiredAzimuthTolerance)
|
|
||||||
||
|
|
||||||
Math.abs(currentAzimuth) <= desiredAzimuth + desiredAzimuthTolerance
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "DeviceOrientation", "Azimuth outside of tolerance area.", 5);
|
Miscellaneous.logEvent("i", "DeviceOrientation", "Azimuth outside of tolerance area.", 5);
|
||||||
if (getTriggerParameter())
|
if (getTriggerParameter())
|
||||||
@ -338,15 +341,7 @@ public class Trigger
|
|||||||
|
|
||||||
if(desiredPitchTolerance < 180)
|
if(desiredPitchTolerance < 180)
|
||||||
{
|
{
|
||||||
if (
|
if (!(desiredPitch - desiredPitchTolerance <= currentPitch && currentPitch <= desiredPitch + desiredPitchTolerance))
|
||||||
!(
|
|
||||||
(
|
|
||||||
Math.abs(currentPitch) <= Math.abs(desiredPitch - desiredPitchTolerance)
|
|
||||||
||
|
|
||||||
Math.abs(currentPitch) <= desiredPitch + desiredPitchTolerance
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "DeviceOrientation", "Pitch outside of tolerance area.", 5);
|
Miscellaneous.logEvent("i", "DeviceOrientation", "Pitch outside of tolerance area.", 5);
|
||||||
if (getTriggerParameter())
|
if (getTriggerParameter())
|
||||||
@ -358,15 +353,7 @@ public class Trigger
|
|||||||
|
|
||||||
if(desiredRollTolerance < 180)
|
if(desiredRollTolerance < 180)
|
||||||
{
|
{
|
||||||
if (
|
if (!(desiredRoll - desiredRollTolerance <= currentRoll && currentRoll <= desiredRoll + desiredRollTolerance))
|
||||||
!(
|
|
||||||
(
|
|
||||||
Math.abs(currentRoll) <= Math.abs(desiredRoll - desiredRollTolerance)
|
|
||||||
||
|
|
||||||
Math.abs(currentRoll) <= desiredRoll + desiredRollTolerance
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
Miscellaneous.logEvent("i", "DeviceOrientation", "Roll outside of tolerance area.", 5);
|
Miscellaneous.logEvent("i", "DeviceOrientation", "Roll outside of tolerance area.", 5);
|
||||||
if (getTriggerParameter())
|
if (getTriggerParameter())
|
||||||
|
BIN
app/src/main/res/drawable/arrow_azimuth.png
Normal file
BIN
app/src/main/res/drawable/arrow_azimuth.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
app/src/main/res/drawable/arrow_pitch.png
Normal file
BIN
app/src/main/res/drawable/arrow_pitch.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/drawable/arrow_roll.png
Normal file
BIN
app/src/main/res/drawable/arrow_roll.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
@ -22,7 +22,14 @@
|
|||||||
|
|
||||||
<TableRow
|
<TableRow
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" >
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical" >
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_marginRight="@dimen/default_margin"
|
||||||
|
android:src="@drawable/arrow_azimuth"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@string/orientationAzimuth"
|
android:text="@string/orientationAzimuth"
|
||||||
@ -39,7 +46,14 @@
|
|||||||
|
|
||||||
<TableRow
|
<TableRow
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" >
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical" >
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_marginRight="@dimen/default_margin"
|
||||||
|
android:src="@drawable/arrow_pitch"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@string/orientationPitch"
|
android:text="@string/orientationPitch"
|
||||||
@ -56,7 +70,14 @@
|
|||||||
|
|
||||||
<TableRow
|
<TableRow
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" >
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical" >
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_marginRight="@dimen/default_margin"
|
||||||
|
android:src="@drawable/arrow_roll"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@string/orientationRoll"
|
android:text="@string/orientationRoll"
|
||||||
|
@ -54,6 +54,16 @@
|
|||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
||||||
|
<TableRow>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_span="2"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/profileTriggerCheckSettings" />
|
||||||
|
|
||||||
|
</TableRow>
|
||||||
|
|
||||||
</TableLayout>
|
</TableLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
@ -630,7 +630,7 @@
|
|||||||
<string name="deviceOrientationTimeAcceptIntervalTitle">Signal Häufigkeit</string>
|
<string name="deviceOrientationTimeAcceptIntervalTitle">Signal Häufigkeit</string>
|
||||||
<string name="deviceOrientationTimeAcceptIntervalSummary">Neue Signale nur alle x Millisekunden akzeptieren</string>
|
<string name="deviceOrientationTimeAcceptIntervalSummary">Neue Signale nur alle x Millisekunden akzeptieren</string>
|
||||||
<string name="deviceOrientationSettings">Geräteausrichtungseinstellungen</string>
|
<string name="deviceOrientationSettings">Geräteausrichtungseinstellungen</string>
|
||||||
<string name="explanationDeviceOrientationDirection">Wenn das Häkchen gesetzt ist, bedeutet das, daß das Geräte in der angegebenen Ausrichtung sein muß. Wenn es nicht gesetzt ist, führt jede andere Ausrichtung zu einem positiven Ergebnis.</string>
|
<string name="explanationDeviceOrientationDirection">Wenn das Häkchen gesetzt ist, bedeutet das, daß das Gerät in der angegebenen Ausrichtung sein muß. Wenn es nicht gesetzt ist, führt jede andere Ausrichtung zu einem positiven Ergebnis.</string>
|
||||||
<string name="deviceOrientationExplanation">Wenn Sie Ihr Gerät bewegen, werden die Zahlen unten aktualisiert. Was Sie hier sehen können, ist die momentane Ausrichtung Ihres Geräts, gemessen in Grad. Wenn das Gerät in der gewünschten Ausrichtung ist, klicken Sie den \"übernehmen\" Knopf, um die Werte in die \"gewünscht\" Felder zu übertragen.\nWeil es sehr unwahrscheinlich ist, daß Sie diese exakte Ausrichtung jemals wieder erreichen, müssen Sie Toleranzen eingeben. Dies ist der Winkel in Grad, der in jede Richtung noch akzeptiert wird. 15° entsprechen somit einem Gesamtwinkel von 30°, 15 in jede Richtung.\nWenn Ihnen nur eine bestimmte Achse wichtig ist, können Sie eine Toleranz von 180° für die anderen beiden Richtungen angeben.</string>
|
<string name="deviceOrientationExplanation">Wenn Sie Ihr Gerät bewegen, werden die Zahlen unten aktualisiert. Was Sie hier sehen können, ist die momentane Ausrichtung Ihres Geräts, gemessen in Grad. Wenn das Gerät in der gewünschten Ausrichtung ist, klicken Sie den \"übernehmen\" Knopf, um die Werte in die \"gewünscht\" Felder zu übertragen.\nWeil es sehr unwahrscheinlich ist, daß Sie diese exakte Ausrichtung jemals wieder erreichen, müssen Sie Toleranzen eingeben. Dies ist der Winkel in Grad, der in jede Richtung noch akzeptiert wird. 15° entsprechen somit einem Gesamtwinkel von 30°, 15 in jede Richtung.\nWenn Ihnen nur eine bestimmte Achse wichtig ist, können Sie eine Toleranz von 180° für die anderen beiden Richtungen angeben.</string>
|
||||||
<string name="actionSetBluetoothTethering">Bluetooth Tethering</string>
|
<string name="actionSetBluetoothTethering">Bluetooth Tethering</string>
|
||||||
<string name="actionTurnBluetoothTetheringOn">Bluetooth Tethering einschalten</string>
|
<string name="actionTurnBluetoothTetheringOn">Bluetooth Tethering einschalten</string>
|
||||||
@ -640,4 +640,13 @@
|
|||||||
<string name="triggerWrong">Mit diesem Auslöser stimmt etwas nicht. Er konnte nicht korrekt geladen werden.</string>
|
<string name="triggerWrong">Mit diesem Auslöser stimmt etwas nicht. Er konnte nicht korrekt geladen werden.</string>
|
||||||
<string name="android.permission.BIND_DEVICE_ADMIN">Geräte Administrator</string>
|
<string name="android.permission.BIND_DEVICE_ADMIN">Geräte Administrator</string>
|
||||||
<string name="deviceAdminNote">Geräte Administrator Rechte werden für mindestens 1 Regel benötigt, die Sie angelegt haben.</string>
|
<string name="deviceAdminNote">Geräte Administrator Rechte werden für mindestens 1 Regel benötigt, die Sie angelegt haben.</string>
|
||||||
|
<string name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS">Von der Akku-Optimierung ausschließen</string>
|
||||||
|
<string name="recommendedForBetterReliability">Empfohlen für bessere Zuverlässigkeit</string>
|
||||||
|
<string name="needsToBeActive">Muß aktiv sein</string>
|
||||||
|
<string name="checkSettings">Einstellungen überprüfen</string>
|
||||||
|
<string name="profileActive">Profil %1$s ist aktiv</string>
|
||||||
|
<string name="profileNotActive">Profil %1$s ist nicht aktiv</string>
|
||||||
|
<string name="profileTriggerCheckSettings">Wenn dieses Häkchen nicht gesetzt ist, wird nur geprüft, ob das ausgewählte Profil zuletzt aktiviert wurde. Es ist egal, ob Audio-Einstellungen von außerhalb verändert wurden.\nWenn das Häkchen aber gesetzt ist, müssen die aktuellen Audio-Einstellungen auch wirklich genau so gesetzt sein, wie im Profil definiert. ACHTUNG: Der Klingelton selbst kann derzeit noch nicht überprüft werden.</string>
|
||||||
|
<string name="profileCouldNotBeDeleted">Profil konnte nicht gelöscht werden.</string>
|
||||||
|
<string name="ruleXIsUsingProfileY">Dieses Profil kann nicht gelöscht werden. Regel %s$1 verwendet noch Profil %s$2.</string>
|
||||||
</resources>
|
</resources>
|
@ -639,4 +639,13 @@
|
|||||||
<string name="wifiApi30">Porque Google arruinó otra parte de Android, a partir de API 30 solo se puede mostrar los wifi actualmente visibles, ya no todos que su positivo tiene conectados.</string>
|
<string name="wifiApi30">Porque Google arruinó otra parte de Android, a partir de API 30 solo se puede mostrar los wifi actualmente visibles, ya no todos que su positivo tiene conectados.</string>
|
||||||
<string name="smsDialogNotice">Si no ha utilizado una acción de envío de sms en este programa antes, Android puede mostrar un diálogo de confirmación adicional, pidiéndole que permita el envío de mensajes. Debe seleccionar la casilla de verificación \"permitir siempre\" y confirmar si desea que esta acción funcione en segundo plano. Se recomienda ejecutar esta regla manualmente una vez para provocar este diálogo de confirmación.</string>
|
<string name="smsDialogNotice">Si no ha utilizado una acción de envío de sms en este programa antes, Android puede mostrar un diálogo de confirmación adicional, pidiéndole que permita el envío de mensajes. Debe seleccionar la casilla de verificación \"permitir siempre\" y confirmar si desea que esta acción funcione en segundo plano. Se recomienda ejecutar esta regla manualmente una vez para provocar este diálogo de confirmación.</string>
|
||||||
<string name="deviceOrientationExplanation">Cuando mueva su dispositivo, los siguientes números se actualizarán. Lo que puede ver allí, es la orientación actual de su dispositivo medida en grados. Si está en la orientación deseada, haga clic en el botón Aplicar para copiar los valores actuales en los campos deseados. Debido a que alcanzar esta orientación exacta nunca más es muy poco probable, también deba ingresar a una tolerancia. Esta es la cantidad de grados a los que la orientación puede desviarse en cualquier dirección. 15° resultará en un ángulo total de 30°, 15° en todas las direcciones. Si solo le importa un eje específico, especifique una tolerancia de 180° para los otros dos.</string>
|
<string name="deviceOrientationExplanation">Cuando mueva su dispositivo, los siguientes números se actualizarán. Lo que puede ver allí, es la orientación actual de su dispositivo medida en grados. Si está en la orientación deseada, haga clic en el botón Aplicar para copiar los valores actuales en los campos deseados. Debido a que alcanzar esta orientación exacta nunca más es muy poco probable, también deba ingresar a una tolerancia. Esta es la cantidad de grados a los que la orientación puede desviarse en cualquier dirección. 15° resultará en un ángulo total de 30°, 15° en todas las direcciones. Si solo le importa un eje específico, especifique una tolerancia de 180° para los otros dos.</string>
|
||||||
|
<string name="profileNotActive">el perfil %1$s no está activo</string>
|
||||||
|
<string name="profileActive">el perfil %1$s está activo</string>
|
||||||
|
<string name="checkSettings">Comprobar la configuración</string>
|
||||||
|
<string name="needsToBeActive">Necesita estar activo</string>
|
||||||
|
<string name="recommendedForBetterReliability">Recomendado para una mejor fiabilidad</string>
|
||||||
|
<string name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS">Excluir de la optimización de la batería</string>
|
||||||
|
<string name="profileTriggerCheckSettings">Si esta casilla de verificación no está desactivada, solo se marcará si el perfil seleccionado ha sido el último en activarse. No importa si alguna configuración relacionada con el audio se ha cambiado externamente.\nSin embargo, si la casilla de verificación está habilitada, la configuración de audio actual realmente debe ser como se define en el perfil. CUIDADO: La comprobación del archivo de tono de llamada no es compatible actualmente, todavía.</string>
|
||||||
|
<string name="ruleXIsUsingProfileY">No se puede eliminar este perfil. La regla %s$1 hace referencia al perfil %s$2.</string>
|
||||||
|
<string name="profileCouldNotBeDeleted">No se pudo eliminar el perfil.</string>
|
||||||
</resources>
|
</resources>
|
@ -640,4 +640,13 @@
|
|||||||
<string name="deviceOrientationSettings">Impostazioni di orientamento del dispositivo</string>
|
<string name="deviceOrientationSettings">Impostazioni di orientamento del dispositivo</string>
|
||||||
<string name="android.permission.BIND_DEVICE_ADMIN">Amministrazione dispositivo</string>
|
<string name="android.permission.BIND_DEVICE_ADMIN">Amministrazione dispositivo</string>
|
||||||
<string name="deviceAdminNote">I permessi di amministratore del dispositivo sono necessari per almeno 1 delle regole che hai creato.</string>
|
<string name="deviceAdminNote">I permessi di amministratore del dispositivo sono necessari per almeno 1 delle regole che hai creato.</string>
|
||||||
|
<string name="profileTriggerCheckSettings">Se questa casella di controllo non è disabilitata, verrà selezionata solo se il profilo selezionato è stato l\'ultimo ad essere attivato. Non importa se le impostazioni relative all\'audio sono state modificate esternamente.\nTuttavia, se la casella di controllo è abilitata, le impostazioni audio correnti devono essere definite nel profilo. ATTENZIONE: il controllo del file della suoneria non è ancora supportato.</string>
|
||||||
|
<string name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS">Escludere dall\'ottimizzazione della batteria</string>
|
||||||
|
<string name="recommendedForBetterReliability">Consigliato per una migliore affidabilità</string>
|
||||||
|
<string name="needsToBeActive">Deve essere attivo</string>
|
||||||
|
<string name="checkSettings">Controlla le impostazioni</string>
|
||||||
|
<string name="profileActive">profilo %1$s è attivo</string>
|
||||||
|
<string name="profileNotActive">profilo %1$s non attivo</string>
|
||||||
|
<string name="ruleXIsUsingProfileY">Impossibile eliminare questo profilo. La regola %s$1 fa riferimento al profilo %s$2.</string>
|
||||||
|
<string name="profileCouldNotBeDeleted">Impossibile eliminare il profilo.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -638,4 +638,13 @@
|
|||||||
<string name="btTetheringNotice">Deze functie werkt naar verluidt tot Android 8.0. Vanaf een hogere versie werkt het niet meer, maar door een gebrek aan fysieke apparaten kan ik niet zeggen welke dat is. Op Android 11 werkt het absoluut niet meer. Als je een versie tussendoor hebt, laat het me dan weten of het werkt of niet.</string>
|
<string name="btTetheringNotice">Deze functie werkt naar verluidt tot Android 8.0. Vanaf een hogere versie werkt het niet meer, maar door een gebrek aan fysieke apparaten kan ik niet zeggen welke dat is. Op Android 11 werkt het absoluut niet meer. Als je een versie tussendoor hebt, laat het me dan weten of het werkt of niet.</string>
|
||||||
<string name="deviceOrientationExplanation">Wanneer u uw apparaat verplaatst, worden de onderstaande nummers bijgewerkt. Wat je daar kunt zien, is de huidige oriëntatie van je apparaat gemeten in graden. Als het zich in de gewenste richting bevindt, klikt u op de knop Toepassen om de huidige waarden naar de gewenste velden te kopiëren.\nOmdat het zeer onwaarschijnlijk is dat u deze exacte oriëntatie ooit nog bereikt, moet u ook een tolerantie invoeren. Dit is het aantal graden waarin de oriëntatie in beide richtingen kan afwijken. 15° resulteert in een totale hoek van 30°, 15° in elke richting.\nAls u slechts om één specifieke as geeft, geef dan een tolerantie van 180° op voor de twee andere.</string>
|
<string name="deviceOrientationExplanation">Wanneer u uw apparaat verplaatst, worden de onderstaande nummers bijgewerkt. Wat je daar kunt zien, is de huidige oriëntatie van je apparaat gemeten in graden. Als het zich in de gewenste richting bevindt, klikt u op de knop Toepassen om de huidige waarden naar de gewenste velden te kopiëren.\nOmdat het zeer onwaarschijnlijk is dat u deze exacte oriëntatie ooit nog bereikt, moet u ook een tolerantie invoeren. Dit is het aantal graden waarin de oriëntatie in beide richtingen kan afwijken. 15° resulteert in een totale hoek van 30°, 15° in elke richting.\nAls u slechts om één specifieke as geeft, geef dan een tolerantie van 180° op voor de twee andere.</string>
|
||||||
<string name="toleranceOf180OnlyAllowedIn2Fields">Een tolerantie van 180 is alleen toegestaan voor 2 tolerantievelden, niet alle 3. Anders zou de trigger ALTIJD van toepassing zijn.</string>
|
<string name="toleranceOf180OnlyAllowedIn2Fields">Een tolerantie van 180 is alleen toegestaan voor 2 tolerantievelden, niet alle 3. Anders zou de trigger ALTIJD van toepassing zijn.</string>
|
||||||
|
<string name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS">Uitsluiten van batterijoptimalisatie</string>
|
||||||
|
<string name="recommendedForBetterReliability">Aanbevolen voor een betere betrouwbaarheid</string>
|
||||||
|
<string name="needsToBeActive">Moet actief zijn</string>
|
||||||
|
<string name="checkSettings">Instellingen controleren</string>
|
||||||
|
<string name="profileActive">profile %1$s is actief</string>
|
||||||
|
<string name="profileNotActive">profile %1$s is niet actief</string>
|
||||||
|
<string name="profileTriggerCheckSettings">Als dit selectievakje niet is uitgeschakeld, wordt het alleen aangevinkt als het geselecteerde profiel het laatste is dat is geactiveerd. Het maakt niet uit of audiogerelateerde instellingen extern zijn gewijzigd.\nAls het selectievakje echter is ingeschakeld, moeten de huidige audio-instellingen echt worden gedefinieerd in het profiel. PAS OP: Het controleren van het beltoonbestand wordt momenteel nog niet ondersteund.</string>
|
||||||
|
<string name="ruleXIsUsingProfileY">Kan dit profiel niet verwijderen. Regel %s$1 verwijst naar het profiel %s$2.</string>
|
||||||
|
<string name="profileCouldNotBeDeleted">Profiel kan niet worden verwijderd.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -742,4 +742,7 @@
|
|||||||
<string name="checkSettings">Check settings</string>
|
<string name="checkSettings">Check settings</string>
|
||||||
<string name="profileActive">profile %1$s is active</string>
|
<string name="profileActive">profile %1$s is active</string>
|
||||||
<string name="profileNotActive">profile %1$s is not active</string>
|
<string name="profileNotActive">profile %1$s is not active</string>
|
||||||
|
<string name="profileTriggerCheckSettings">If this checkbox is not disabled, it will only be checked if the selected profile has been the last one to be activated. It doesn\'t matter if any audio related settings have been changed externally. However if the checkbox is enabled, the current audio settings really need to be like defined in the profile. BEWARE: Checking the ringtone file is currently not supported, yet.</string>
|
||||||
|
<string name="ruleXIsUsingProfileY">Cannot delete this profile. Rule %s$1 is referencing profile %s$2.</string>
|
||||||
|
<string name="profileCouldNotBeDeleted">Profile could not be deleted.</string>
|
||||||
</resources>
|
</resources>
|
@ -1,2 +1,3 @@
|
|||||||
* Exclusion from battery optimization
|
* New permission requested: Exclusion from battery optimization
|
||||||
* Profiles can be used as trigger
|
* New trigger: Profiles can be used as trigger
|
||||||
|
* Fixed: Bug in orientation trigger
|
Loading…
Reference in New Issue
Block a user