mirror of
https://github.com/zero-peak/ZeroOmega.git
synced 2025-01-22 15:08:12 -05:00
Allow editing switch profiles as omega rule list. Fix #80.
This commit is contained in:
parent
a54e02b503
commit
75ecb9aa46
@ -98,6 +98,47 @@
|
||||
"ruleList_usageUrl": {
|
||||
"message": "https://github.com/FelisCatus/SwitchyOmega/wiki/RuleListUsage"
|
||||
},
|
||||
"ruleList_error_resultNotEnabled": {
|
||||
"message": "Missing '@with result' directive!"
|
||||
},
|
||||
"ruleList_error_unknownProfile": {
|
||||
"message": "Unknown profile: $PROFILE$",
|
||||
"placeholders": {
|
||||
"profile": {
|
||||
"content": "$1",
|
||||
"example": "some profile"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_missingResultProfile": {
|
||||
"message": "Missing result profile name at Line $LNO$: $SOURCE$",
|
||||
"placeholders": {
|
||||
"lno": {
|
||||
"content": "$1",
|
||||
"example": "11"
|
||||
},
|
||||
"source": {
|
||||
"content": "$2",
|
||||
"example": "*.example.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_invalidRule": {
|
||||
"message": "Invalid rule at Line $LNO$: $SOURCE$",
|
||||
"placeholders": {
|
||||
"lno": {
|
||||
"content": "$1",
|
||||
"example": "11"
|
||||
},
|
||||
"source": {
|
||||
"content": "$2",
|
||||
"example": ":invalid rule"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_noDefaultRule": {
|
||||
"message": "Missing default rule with catch-all '*' condition!"
|
||||
},
|
||||
|
||||
"dialog_close": {
|
||||
"message": "Close"
|
||||
@ -344,6 +385,15 @@
|
||||
"options_profileUnsupportedHelp": {
|
||||
"message": "The options could be broken, or from a newer version of this program."
|
||||
},
|
||||
"options_profileEditSource": {
|
||||
"message": "Edit source code"
|
||||
},
|
||||
"options_profileEditSourceHelp": {
|
||||
"message": "Show help about the source code format"
|
||||
},
|
||||
"options_profileEditSourceHelpUrl": {
|
||||
"message": "https://github.com/FelisCatus/SwitchyOmega/wiki/SwitchyOmega-conditions-format#result-profile"
|
||||
},
|
||||
"options_group_proxyServers": {
|
||||
"message": "Proxy servers"
|
||||
},
|
||||
|
@ -98,6 +98,47 @@
|
||||
"ruleList_usageUrl": {
|
||||
"message": "https://github.com/FelisCatus/SwitchyOmega/wiki/RuleListUsage"
|
||||
},
|
||||
"ruleList_error_resultNotEnabled": {
|
||||
"message": "语法错误:缺少 '@with result' 指令。"
|
||||
},
|
||||
"ruleList_error_unknownProfile": {
|
||||
"message": "Unknown profile: $PROFILE$",
|
||||
"placeholders": {
|
||||
"profile": {
|
||||
"content": "$1",
|
||||
"example": "some profile"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_missingResultProfile": {
|
||||
"message": "语法错误:缺少结果情景模式名称。 行号 $LNO$: $SOURCE$",
|
||||
"placeholders": {
|
||||
"lno": {
|
||||
"content": "$1",
|
||||
"example": "11"
|
||||
},
|
||||
"source": {
|
||||
"content": "$2",
|
||||
"example": "*.example.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_invalidRule": {
|
||||
"message": "语法错误:非法规则。行号 $LNO$: $SOURCE$",
|
||||
"placeholders": {
|
||||
"lno": {
|
||||
"content": "$1",
|
||||
"example": "11"
|
||||
},
|
||||
"source": {
|
||||
"content": "$2",
|
||||
"example": ":invalid rule"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_noDefaultRule": {
|
||||
"message": "语法错误:缺少匹配全部请求的默认规则。应在最后添加'*'规则和默认情景模式。"
|
||||
},
|
||||
|
||||
"dialog_close": {
|
||||
"message": "关闭"
|
||||
@ -344,6 +385,15 @@
|
||||
"options_profileUnsupportedHelp": {
|
||||
"message": "选项文件已经损坏,或者当前版本过低无法处理选项。"
|
||||
},
|
||||
"options_profileEditSource": {
|
||||
"message": "编辑源代码"
|
||||
},
|
||||
"options_profileEditSourceHelp": {
|
||||
"message": "显示源代码格式相关的帮助"
|
||||
},
|
||||
"options_profileEditSourceHelpUrl": {
|
||||
"message": "https://github.com/FelisCatus/SwitchyOmega/wiki/SwitchyOmega-conditions-format#result-profile"
|
||||
},
|
||||
"options_group_proxyServers": {
|
||||
"message": "代理服务器"
|
||||
},
|
||||
|
@ -98,6 +98,47 @@
|
||||
"ruleList_usageUrl": {
|
||||
"message": "https://github.com/FelisCatus/SwitchyOmega/wiki/RuleListUsage"
|
||||
},
|
||||
"ruleList_error_resultNotEnabled": {
|
||||
"message": "語法錯誤:缺少 '@with result' 指令。"
|
||||
},
|
||||
"ruleList_error_unknownProfile": {
|
||||
"message": "Unknown profile: $PROFILE$",
|
||||
"placeholders": {
|
||||
"profile": {
|
||||
"content": "$1",
|
||||
"example": "some profile"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_missingResultProfile": {
|
||||
"message": "語法錯誤:缺少結果情景模式名稱。 行號 $LNO$: $SOURCE$",
|
||||
"placeholders": {
|
||||
"lno": {
|
||||
"content": "$1",
|
||||
"example": "11"
|
||||
},
|
||||
"source": {
|
||||
"content": "$2",
|
||||
"example": "*.example.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_invalidRule": {
|
||||
"message": "語法錯誤:非法規則。行號 $LNO$: $SOURCE$",
|
||||
"placeholders": {
|
||||
"lno": {
|
||||
"content": "$1",
|
||||
"example": "11"
|
||||
},
|
||||
"source": {
|
||||
"content": "$2",
|
||||
"example": ":invalid rule"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_noDefaultRule": {
|
||||
"message": "語法錯誤:缺少匹配全部請求的預設規則。應在最後新增'*'規則和預設情景模式。"
|
||||
},
|
||||
|
||||
"dialog_close": {
|
||||
"message": "關閉"
|
||||
@ -344,6 +385,15 @@
|
||||
"options_profileUnsupportedHelp": {
|
||||
"message": "選項文件已經損壞,或者當前版本過低無法處理選項。"
|
||||
},
|
||||
"options_profileEditSource": {
|
||||
"message": "編輯原始碼"
|
||||
},
|
||||
"options_profileEditSourceHelp": {
|
||||
"message": "顯示原始碼格式相關的幫助"
|
||||
},
|
||||
"options_profileEditSourceHelpUrl": {
|
||||
"message": "https://github.com/FelisCatus/SwitchyOmega/wiki/SwitchyOmega-conditions-format#result-profile"
|
||||
},
|
||||
"options_group_proxyServers": {
|
||||
"message": "代理服務器"
|
||||
},
|
||||
|
@ -98,6 +98,47 @@
|
||||
"ruleList_usageUrl": {
|
||||
"message": "https://github.com/FelisCatus/SwitchyOmega/wiki/RuleListUsage"
|
||||
},
|
||||
"ruleList_error_resultNotEnabled": {
|
||||
"message": "語法錯誤:缺少 '@with result' 指令。"
|
||||
},
|
||||
"ruleList_error_unknownProfile": {
|
||||
"message": "Unknown profile: $PROFILE$",
|
||||
"placeholders": {
|
||||
"profile": {
|
||||
"content": "$1",
|
||||
"example": "some profile"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_missingResultProfile": {
|
||||
"message": "語法錯誤:缺少結果情景模式名稱。 行號 $LNO$: $SOURCE$",
|
||||
"placeholders": {
|
||||
"lno": {
|
||||
"content": "$1",
|
||||
"example": "11"
|
||||
},
|
||||
"source": {
|
||||
"content": "$2",
|
||||
"example": "*.example.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_invalidRule": {
|
||||
"message": "語法錯誤:非法規則。行號 $LNO$: $SOURCE$",
|
||||
"placeholders": {
|
||||
"lno": {
|
||||
"content": "$1",
|
||||
"example": "11"
|
||||
},
|
||||
"source": {
|
||||
"content": "$2",
|
||||
"example": ":invalid rule"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ruleList_error_noDefaultRule": {
|
||||
"message": "語法錯誤:缺少匹配全部請求的預設規則。應在最後新增'*'規則和預設情景模式。"
|
||||
},
|
||||
|
||||
"dialog_close": {
|
||||
"message": "關閉"
|
||||
@ -344,6 +385,15 @@
|
||||
"options_profileUnsupportedHelp": {
|
||||
"message": "選項檔案已經損壞,或者當前版本過低無法處理選項。"
|
||||
},
|
||||
"options_profileEditSource": {
|
||||
"message": "編輯原始碼"
|
||||
},
|
||||
"options_profileEditSourceHelp": {
|
||||
"message": "顯示原始碼格式相關的幫助"
|
||||
},
|
||||
"options_profileEditSourceHelpUrl": {
|
||||
"message": "https://github.com/FelisCatus/SwitchyOmega/wiki/SwitchyOmega-conditions-format#result-profile"
|
||||
},
|
||||
"options_group_proxyServers": {
|
||||
"message": "代理伺服器"
|
||||
},
|
||||
|
@ -70,7 +70,7 @@ module.exports = exports =
|
||||
switchy = exports['Switchy']
|
||||
parser = switchy.getParser(text)
|
||||
return unless parser == 'parseOmega'
|
||||
return unless /(^|\n)@with\s+results?(\r|\n)/i.test(text)
|
||||
return unless /(^|\n)@with\s+results?(\r|\n|$)/i.test(text)
|
||||
refs = {}
|
||||
for line in text.split(/\n|\r/)
|
||||
line = line.trim()
|
||||
@ -107,7 +107,7 @@ module.exports = exports =
|
||||
ruleList += line + eol
|
||||
if withResult
|
||||
# TODO(catus): Also special chars and sequences in defaultProfileName.
|
||||
ruleList += '* +' + defaultProfileName + eol
|
||||
ruleList += eol + '* +' + defaultProfileName + eol
|
||||
return ruleList
|
||||
|
||||
getParser: (text) ->
|
||||
@ -174,11 +174,20 @@ module.exports = exports =
|
||||
|
||||
parseOmega: (text, matchProfileName, defaultProfileName, args = {}) ->
|
||||
{strict} = args
|
||||
if strict
|
||||
error = (fields) ->
|
||||
err = new Error(fields.message)
|
||||
for own key, value of fields
|
||||
err[key] = value
|
||||
throw err
|
||||
includeSource = args.source ? true
|
||||
rules = []
|
||||
rulesWithDefaultProfile = []
|
||||
withResult = false
|
||||
exclusiveProfile = null
|
||||
lno = 0
|
||||
for line in text.split(/\n|\r/)
|
||||
lno++
|
||||
line = line.trim()
|
||||
continue if line.length == 0
|
||||
switch line[0]
|
||||
@ -199,6 +208,7 @@ module.exports = exports =
|
||||
continue
|
||||
|
||||
source = null
|
||||
exclusiveProfile = null if strict
|
||||
if line[0] == '!'
|
||||
profile = if withResult then null else defaultProfileName
|
||||
source = line
|
||||
@ -206,7 +216,12 @@ module.exports = exports =
|
||||
else if withResult
|
||||
iSpace = line.lastIndexOf(' +')
|
||||
if iSpace < 0
|
||||
throw new Error("Missing result profile name: " + line) if strict
|
||||
error?({
|
||||
message: "Missing result profile name: " + line
|
||||
reason: 'missingResultProfile'
|
||||
source: line
|
||||
sourceLineNo: lno
|
||||
})
|
||||
continue
|
||||
profile = line.substr(iSpace + 2).trim()
|
||||
line = line.substr(0, iSpace).trim()
|
||||
@ -216,10 +231,18 @@ module.exports = exports =
|
||||
|
||||
cond = Conditions.fromStr(line)
|
||||
if not cond
|
||||
throw new Error("Invalid rule: " + line) if strict
|
||||
error?({
|
||||
message: "Invalid rule: " + line
|
||||
reason: 'invalidRule'
|
||||
source: source ? line
|
||||
sourceLineNo: lno
|
||||
})
|
||||
continue
|
||||
|
||||
rule = {condition: cond, profileName: profile, source: source ? line}
|
||||
rule =
|
||||
condition: cond
|
||||
profileName: profile
|
||||
source: if includeSource then source ? line
|
||||
rules.push(rule)
|
||||
if not profile
|
||||
rulesWithDefaultProfile.push(rule)
|
||||
@ -227,7 +250,10 @@ module.exports = exports =
|
||||
if withResult
|
||||
if not exclusiveProfile
|
||||
if strict
|
||||
throw new Error("Missing default rule with catch-all '*' condition")
|
||||
error?({
|
||||
message: "Missing default rule with catch-all '*' condition"
|
||||
reason: 'noDefaultRule'
|
||||
})
|
||||
exclusiveProfile = defaultProfileName || 'direct'
|
||||
for rule in rulesWithDefaultProfile
|
||||
rule.profileName = exclusiveProfile
|
||||
|
@ -78,6 +78,7 @@ angular.module('omega').controller 'MasterCtrl', ($scope, $rootScope, $window,
|
||||
|
||||
$rootScope.applyOptions = ->
|
||||
return unless checkFormValid()
|
||||
return if $rootScope.$broadcast('omegaApplyOptions').defaultPrevented
|
||||
plainOptions = angular.fromJson(angular.toJson($rootScope.options))
|
||||
patch = diff.diff($rootScope.optionsOld, plainOptions)
|
||||
omegaTarget.optionsPatch(patch).then ->
|
||||
|
@ -1,6 +1,57 @@
|
||||
angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
$modal, profileIcons, getAttachedName, omegaTarget, $timeout, trFilter) ->
|
||||
angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $rootScope,
|
||||
$location, $timeout, $q, $modal, profileIcons, getAttachedName, omegaTarget,
|
||||
trFilter) ->
|
||||
# == Rule list ==
|
||||
$scope.ruleListFormats = OmegaPac.Profiles.ruleListFormats
|
||||
|
||||
exportRuleList = ->
|
||||
text = OmegaPac.RuleList.Switchy.compose($scope.profile)
|
||||
|
||||
eol = '\r\n'
|
||||
info = '\n'
|
||||
info += '; Require: SwitchyOmega >= 2.3.2' + eol
|
||||
info += "; Date: #{new Date().toLocaleDateString()}" + eol
|
||||
info += "; Usage: #{trFilter('ruleList_usageUrl')}" + eol
|
||||
|
||||
text = text.replace('\n', info)
|
||||
|
||||
blob = new Blob [text], {type: "text/plain;charset=utf-8"}
|
||||
fileName = $scope.profile.name.replace(/\W+/g, '_')
|
||||
saveAs(blob, "OmegaRules_#{fileName}.sorl")
|
||||
|
||||
exportLegacyRuleList = ->
|
||||
wildcardRules = ''
|
||||
regexpRules = ''
|
||||
for rule in $scope.profile.rules
|
||||
i = ''
|
||||
if rule.profileName == $scope.attachedOptions.defaultProfileName
|
||||
i = '!'
|
||||
switch rule.condition.conditionType
|
||||
when 'HostWildcardCondition'
|
||||
wildcardRules += i + '@*://' + rule.condition.pattern + '/*' + '\r\n'
|
||||
when 'UrlWildcardCondition'
|
||||
wildcardRules += i + '@' + rule.condition.pattern + '\r\n'
|
||||
when 'UrlRegexCondition'
|
||||
regexpRules += i + rule.condition.pattern + '\r\n'
|
||||
|
||||
text = """
|
||||
; Summary: Proxy Switchy! Exported Rule List
|
||||
; Date: #{new Date().toLocaleDateString()}
|
||||
; Website: http://bit.ly/proxyswitchy
|
||||
|
||||
#BEGIN
|
||||
|
||||
[wildcard]
|
||||
#{wildcardRules}
|
||||
[regexp]
|
||||
#{regexpRules}
|
||||
#END
|
||||
"""
|
||||
blob = new Blob [text], {type: "text/plain;charset=utf-8"}
|
||||
fileName = $scope.profile.name.replace(/\W+/g, '_')
|
||||
saveAs(blob, "SwitchyRules_#{fileName}.ssrl")
|
||||
|
||||
# == Condition types ==
|
||||
$scope.showConditionHelp = ($location.search().help == 'condition')
|
||||
|
||||
$scope.basicConditionTypes = [
|
||||
@ -40,53 +91,6 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
}
|
||||
]
|
||||
|
||||
exportRuleList = ->
|
||||
text = OmegaPac.RuleList.Switchy.compose($scope.profile)
|
||||
|
||||
eol = '\r\n'
|
||||
info = '\n'
|
||||
info += '; Require: SwitchyOmega >= 2.3.2' + eol
|
||||
info += "; Date: #{new Date().toLocaleDateString()}" + eol
|
||||
info += "; Usage: #{trFilter('ruleList_usageUrl')}" + eol
|
||||
|
||||
text = text.replace('\n', info)
|
||||
|
||||
blob = new Blob [text], {type: "text/plain;charset=utf-8"}
|
||||
fileName = $scope.profile.name.replace(/\W+/g, '_')
|
||||
saveAs(blob, "OmegaRules_#{fileName}.sorl")
|
||||
|
||||
exportLegacyRuleList = ->
|
||||
wildcardRules = ''
|
||||
regexpRules = ''
|
||||
for rule in $scope.profile.rules
|
||||
i = ''
|
||||
if rule.profileName == $scope.defaultProfileName
|
||||
i = '!'
|
||||
switch rule.condition.conditionType
|
||||
when 'HostWildcardCondition'
|
||||
wildcardRules += i + '@*://' + rule.condition.pattern + '/*' + '\r\n'
|
||||
when 'UrlWildcardCondition'
|
||||
wildcardRules += i + '@' + rule.condition.pattern + '\r\n'
|
||||
when 'UrlRegexCondition'
|
||||
regexpRules += i + rule.condition.pattern + '\r\n'
|
||||
|
||||
text = """
|
||||
; Summary: Proxy Switchy! Exported Rule List
|
||||
; Date: #{new Date().toLocaleDateString()}
|
||||
; Website: http://bit.ly/proxyswitchy
|
||||
|
||||
#BEGIN
|
||||
|
||||
[wildcard]
|
||||
#{wildcardRules}
|
||||
[regexp]
|
||||
#{regexpRules}
|
||||
#END
|
||||
"""
|
||||
blob = new Blob [text], {type: "text/plain;charset=utf-8"}
|
||||
fileName = $scope.profile.name.replace(/\W+/g, '_')
|
||||
saveAs(blob, "SwitchyRules_#{fileName}.ssrl")
|
||||
|
||||
expandGroups = (groups) ->
|
||||
result = []
|
||||
for group in groups
|
||||
@ -149,6 +153,14 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
if $scope.hasConditionTypes == 0
|
||||
unwatchRules = $scope.$watch 'profile.rules', updateHasConditionTypes, true
|
||||
|
||||
# == Rules ==
|
||||
rulesReadyDefer = $q.defer()
|
||||
rulesReady = rulesReadyDefer.promise
|
||||
stopWatchingForRules = $scope.$watch 'profile.rules', (rules) ->
|
||||
return unless rules
|
||||
stopWatchingForRules()
|
||||
rulesReadyDefer.resolve(rules)
|
||||
|
||||
$scope.addRule = ->
|
||||
rule =
|
||||
if $scope.profile.rules.length > 0
|
||||
@ -156,7 +168,7 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
angular.copy(templ)
|
||||
else
|
||||
condition: {conditionType: 'HostWildcardCondition', pattern: ''}
|
||||
profileName: $scope.profile.defaultProfileName
|
||||
profileName: $scope.attachedOptions.defaultProfileName
|
||||
if rule.condition.pattern
|
||||
rule.condition.pattern = ''
|
||||
$scope.profile.rules.push rule
|
||||
@ -201,7 +213,8 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
|
||||
$scope.resetRules = ->
|
||||
scope = $scope.$new('isolate')
|
||||
scope.ruleProfile = $scope.profileByName($scope.defaultProfileName)
|
||||
scope.ruleProfile =
|
||||
$scope.profileByName($scope.attachedOptions.defaultProfileName)
|
||||
scope.dispNameFilter = $scope.dispNameFilter
|
||||
scope.options = $scope.options
|
||||
$modal.open(
|
||||
@ -209,7 +222,7 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
scope: scope
|
||||
).result.then ->
|
||||
for rule in $scope.profile.rules
|
||||
rule.profileName = $scope.defaultProfileName
|
||||
rule.profileName = $scope.attachedOptions.defaultProfileName
|
||||
|
||||
$scope.sortableOptions =
|
||||
handle: '.sort-bar'
|
||||
@ -219,8 +232,9 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
forcePlaceholderSize: true
|
||||
containment: 'parent'
|
||||
|
||||
$scope.ruleListFormats = OmegaPac.Profiles.ruleListFormats
|
||||
|
||||
# == Attached ==
|
||||
attachedReadyDefer = $q.defer()
|
||||
attachedReady = attachedReadyDefer.promise
|
||||
$scope.$watch 'profile.name', (name) ->
|
||||
$scope.attachedName = getAttachedName(name)
|
||||
$scope.attachedKey = OmegaPac.Profiles.nameAsKey($scope.attachedName)
|
||||
@ -250,7 +264,7 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
$scope.$watch 'profile.defaultProfileName', (name) ->
|
||||
$scope.attachedOptions.enabled = (name == $scope.attachedName)
|
||||
if not $scope.attached or not $scope.attachedOptions.enabled
|
||||
$scope.defaultProfileName = name
|
||||
$scope.attachedOptions.defaultProfileName = name
|
||||
|
||||
$scope.$watch 'attachedOptions.enabled', (enabled, oldValue) ->
|
||||
return if enabled == oldValue
|
||||
@ -261,16 +275,18 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
if $scope.profile.defaultProfileName == $scope.attachedName
|
||||
if $scope.attached
|
||||
$scope.profile.defaultProfileName = $scope.attached.defaultProfileName
|
||||
$scope.defaultProfileName = $scope.attached.defaultProfileName
|
||||
$scope.attachedOptions.defaultProfileName =
|
||||
$scope.attached.defaultProfileName
|
||||
else
|
||||
$scope.profile.defaultProfileName = 'direct'
|
||||
$scope.defaultProfileName = 'direct'
|
||||
$scope.attachedOptions.defaultProfileName = 'direct'
|
||||
|
||||
$scope.$watch 'attached.defaultProfileName', (name) ->
|
||||
if name and $scope.attachedOptions.enabled
|
||||
$scope.defaultProfileName = name
|
||||
$scope.attachedOptions.defaultProfileName = name
|
||||
|
||||
$scope.$watch 'defaultProfileName', (name) ->
|
||||
$scope.$watch 'attachedOptions.defaultProfileName', (name) ->
|
||||
attachedReadyDefer.resolve()
|
||||
if $scope.attached and $scope.attachedOptions.enabled
|
||||
$scope.attached.defaultProfileName = name
|
||||
else
|
||||
@ -301,11 +317,95 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location,
|
||||
$scope.profile.defaultProfileName = $scope.attached.defaultProfileName
|
||||
delete $scope.options[$scope.attachedKey]
|
||||
|
||||
stopWatchingForGuide = $scope.$watch 'profile.rules', (rules) ->
|
||||
return unless rules
|
||||
stopWatchingForGuide()
|
||||
omegaTarget.state(['web.switchGuide', 'firstRun'
|
||||
]).then ([switchGuide, firstRun]) ->
|
||||
return if firstRun or switchGuide == 'shown'
|
||||
$script 'js/switch_profile_guide.js'
|
||||
omegaTarget.state('web.switchGuide', 'shown')
|
||||
# == Edit source ==
|
||||
stateEditorKey = 'web._profileEditor.' + $scope.profile.name
|
||||
$scope.loadRules = false
|
||||
$scope.editSource = false
|
||||
parseOmegaRules = (code, {detect, requireResult} = {}) ->
|
||||
setError = (error) ->
|
||||
if error.reason
|
||||
args = error.args ? [
|
||||
error.sourceLineNo
|
||||
error.source
|
||||
]
|
||||
message = trFilter('ruleList_error_' + error.reason, args)
|
||||
error.message = message if message
|
||||
return {error: error}
|
||||
if detect and not OmegaPac.RuleList.Switchy.detect(code)
|
||||
return {error: {reason: 'notSwitchy'}}
|
||||
refs = OmegaPac.RuleList.Switchy.directReferenceSet({
|
||||
ruleList: code
|
||||
})
|
||||
if requireResult and not refs
|
||||
return setError({reason: 'resultNotEnabled'})
|
||||
for own key, name of refs
|
||||
if not OmegaPac.Profiles.byKey(key, $scope.options)
|
||||
return setError({reason: 'unknownProfile', args: [name]})
|
||||
try
|
||||
return rules: OmegaPac.RuleList.Switchy.parseOmega(code, null, null,
|
||||
{strict: true, source: false})
|
||||
catch err
|
||||
return setError(err)
|
||||
parseSource = ->
|
||||
return true unless $scope.source
|
||||
{rules, error} = parseOmegaRules($scope.source.code.trim(),
|
||||
requireResult: true)
|
||||
if error
|
||||
$scope.source.error = error
|
||||
$scope.editSource = true
|
||||
return false
|
||||
else
|
||||
$scope.source.error = undefined
|
||||
$scope.attachedOptions.defaultProfileName = rules.pop().profileName
|
||||
# Try to merge with existing rules if possible.
|
||||
diff = jsondiffpatch.create(
|
||||
objectHash: (obj) -> JSON.stringify(obj)
|
||||
textDiff: minLength: 1 / 0
|
||||
)
|
||||
oldRules = angular.fromJson(angular.toJson($scope.profile.rules))
|
||||
patch = diff.diff(oldRules, rules)
|
||||
jsondiffpatch.patch($scope.profile.rules, patch)
|
||||
return true
|
||||
$scope.toggleSource = -> $q.all([attachedReady, rulesReady]).then ->
|
||||
$scope.editSource = not $scope.editSource
|
||||
if $scope.editSource
|
||||
args =
|
||||
rules: $scope.profile.rules
|
||||
defaultProfileName: $scope.attachedOptions.defaultProfileName
|
||||
code = OmegaPac.RuleList.Switchy.compose(args, withResult: true)
|
||||
$scope.source = {code: code}
|
||||
else
|
||||
return unless parseSource()
|
||||
$scope.source = null
|
||||
$scope.loadRules = true
|
||||
omegaTarget.state(stateEditorKey, {editSource: $scope.editSource})
|
||||
|
||||
$scope.$on 'omegaApplyOptions', (event) ->
|
||||
if $scope.attached?.ruleList and not $scope.attached.sourceUrl
|
||||
$scope.attachedRuleListError = undefined
|
||||
{error} = parseOmegaRules($scope.attached.ruleList.trim(), detect: true)
|
||||
if error
|
||||
if error.reason != 'resultNotEnabled' and error.reason != 'notSwitchy'
|
||||
$scope.attachedRuleListError = error
|
||||
event.preventDefault()
|
||||
angular.element('#attached-rulelist')[0].focus()
|
||||
else
|
||||
$scope.attached.format = 'Switchy'
|
||||
|
||||
if $scope.editSource and $scope.source.touched
|
||||
event.preventDefault()
|
||||
if parseSource()
|
||||
$scope.source.touched = false
|
||||
$timeout ->
|
||||
$rootScope.applyOptions()
|
||||
|
||||
omegaTarget.state(stateEditorKey).then (opts) ->
|
||||
if opts?.editSource
|
||||
$scope.toggleSource()
|
||||
else
|
||||
$scope.loadRules = true
|
||||
getState = omegaTarget.state(['web.switchGuide', 'firstRun'])
|
||||
$q.all([rulesReady, getState]).then ([_, [switchGuide, firstRun]]) ->
|
||||
return if firstRun or switchGuide == 'shown'
|
||||
$script 'js/switch_profile_guide.js'
|
||||
omegaTarget.state('web.switchGuide', 'shown')
|
||||
|
@ -6,7 +6,7 @@ section.settings-group
|
||||
.text-info
|
||||
span.glyphicon.glyphicon-info-sign
|
||||
= ' '
|
||||
{{'options_exportProfileHelp' | tr}}
|
||||
| {{'options_exportProfileHelp' | tr}}
|
||||
div.checkbox(ng-show='!(options["-showConditionTypes"] > 0)')
|
||||
label
|
||||
input(type='checkbox' ng-model='options["-exportLegacyRuleList"]')
|
||||
|
@ -15,8 +15,26 @@ div(ng-controller='SwitchProfileCtrl')
|
||||
dt(ng-repeat-start='type in group.types') {{'condition_' + type | tr}}
|
||||
dd(ng-repeat-end ng-bind-html='"condition_help_" + type | tr')
|
||||
section.settings-group
|
||||
h3 {{'options_group_switchRules' | tr}}
|
||||
.table-responsive.switch-rules-wrapper
|
||||
h3
|
||||
| {{'options_group_switchRules' | tr}}
|
||||
= ' '
|
||||
button.btn(ng-click='toggleSource()' ng-class='editSource ? "btn-primary active" : "btn-default"')
|
||||
span.glyphicon.glyphicon-edit
|
||||
= ' '
|
||||
| {{'options_profileEditSource' | tr}}
|
||||
= ' '
|
||||
a.btn.btn-link.btn-sm.clear-padding.toggle-condition-help(
|
||||
ng-show='editSource' target='_blank'
|
||||
title='{{"options_profileEditSourceHelp" | tr}}'
|
||||
href='{{"options_profileEditSourceHelpUrl" | tr}}')
|
||||
span.glyphicon.glyphicon-question-sign
|
||||
.alert.alert-danger.width-limit(ng-show='source.error')
|
||||
span.glyphicon.glyphicon-remove
|
||||
= ' '
|
||||
| {{source.error.message}}
|
||||
.rules-source(ng-show='editSource')
|
||||
textarea.monospace.form-control.width-limit(ng-model='source.code' rows=20 ng-change='source.touched = true; $root.optionsDirty = true')
|
||||
.table-responsive.switch-rules-wrapper(ng-if='loadRules' ng-show='!editSource')
|
||||
table.switch-rules.table.table-bordered.table-condensed.width-limit-xl
|
||||
thead
|
||||
tr
|
||||
@ -94,7 +112,7 @@ div(ng-controller='SwitchProfileCtrl')
|
||||
td
|
||||
td(colspan='2') {{'options_switchDefaultProfile' | tr}}
|
||||
td
|
||||
div(omega-profile-select='options | profiles:profile' ng-model='defaultProfileName'
|
||||
div(omega-profile-select='options | profiles:profile' ng-model='attachedOptions.defaultProfileName'
|
||||
disp-name='dispNameFilter' options='options')
|
||||
td
|
||||
button.btn.btn-info.btn-sm(title="{{'options_resetRules_help' | tr}}" ng-click='resetRules()')
|
||||
@ -131,5 +149,9 @@ div(ng-controller='SwitchProfileCtrl')
|
||||
| {{'options_ruleListLastUpdate' | tr:[(attached.lastUpdate | date:'medium')]}}
|
||||
p.alert.alert-danger.width-limit(ng-show='attached.sourceUrl && !attached.lastUpdate')
|
||||
| {{'options_ruleListObsolete' | tr}}
|
||||
textarea.monospace.form-control.width-limit(ng-model='attached.ruleList' rows=20
|
||||
ng-disabled='!!attached.sourceUrl')
|
||||
p.alert.alert-danger.width-limit(ng-show='attachedRuleListError')
|
||||
span.glyphicon.glyphicon-remove
|
||||
= ' '
|
||||
| {{attachedRuleListError.message}}
|
||||
textarea#attached-rulelist.monospace.form-control.width-limit(rows=20
|
||||
ng-model='attached.ruleList' ng-disabled='!!attached.sourceUrl')
|
||||
|
Loading…
Reference in New Issue
Block a user