diff --git a/omega-i18n/en/messages.json b/omega-i18n/en/messages.json index b97eb09..59872e2 100644 --- a/omega-i18n/en/messages.json +++ b/omega-i18n/en/messages.json @@ -670,6 +670,21 @@ "options_guide_addMoreProfilesStep": { "message": "Need more profiles? You can always add more Proxy, Switch and other profiles
for all your proxying needs.
Enjoy proxying!" }, + "options_guide_conditionStep": { + "message": "SwitchyOmega can apply different profiles to requests based on conditions.
For example, the Host wildcard condition allows you to set the profile for all URLs in a domain." + }, + "options_guide_conditionTypeStep": { + "message": "You can use various condition types to match the host or full URL.
Click on the question mark to open the type reference." + }, + "options_guide_conditionProfileStep": { + "message": "SwitchyOmega applies the selected profile here to any request matching the condition.
The special \"[Direct]\" profile will cause the request to be sent without any proxy." + }, + "options_guide_switchDefaultStep": { + "message": "If no condition applies to some request, the \"Default\" profile will be used.
Conditions are always considered from top to bottom in order.
You can change their order by dragging the sort icon." + }, + "options_guide_applySwitchProfileStep": { + "message": "When you are done setting the switch profile, don't forget to switch to it in the popup menu.
The icon will show you the final result profile applied for the current tab.
Hovering on the icon will reveal a tooltip with details." + }, "popup_externalProfile": { "message": "(External Profile)" }, diff --git a/omega-i18n/zh_CN/messages.json b/omega-i18n/zh_CN/messages.json index f752412..450de16 100644 --- a/omega-i18n/zh_CN/messages.json +++ b/omega-i18n/zh_CN/messages.json @@ -670,6 +670,21 @@ "options_guide_addMoreProfilesStep": { "message": "如果您需要更多的情景模式,可以随时在这里创建代理、切换和其他情景模式
教程到此结束,您可以继续自定义设置。" }, + "options_guide_conditionStep": { + "message": "SwitchyOmega 可以根据切换条件对不同的网络请求使用不同的情景模式。
例如域名通配符条件可以对某个域名下的所有网址使用特定的情景模式。" + }, + "options_guide_conditionTypeStep": { + "message": "您可以使用各种条件类型来匹配域名或者整个网址。
点击问号按钮来查看条件类型的说明。" + }, + "options_guide_conditionProfileStep": { + "message": "对于任何匹配该条件的请求,SwitchyOmega 会使用这个情景模式。
如果选择了\"[直接连接]\"情景模式,则匹配的请求不使用任何代理。" + }, + "options_guide_switchDefaultStep": { + "message": "如果请求不匹配任何条件,则使用默认情景模式。
条件的匹配顺序总是按此页面从上到下
您可以拖动排序图标来更改条件的顺序。" + }, + "options_guide_applySwitchProfileStep": { + "message": "当您设置完毕后,别忘记在弹出菜单中启用自动切换情景模式
图标将会显示标签页切换的最终结果情景。
悬停在图标上则会显示切换相关的详细说明。" + }, "popup_externalProfile": { "message": "(外部情景模式)" }, diff --git a/omega-i18n/zh_HK/messages.json b/omega-i18n/zh_HK/messages.json index 420f42f..bb41176 100644 --- a/omega-i18n/zh_HK/messages.json +++ b/omega-i18n/zh_HK/messages.json @@ -658,6 +658,33 @@ "options_downloadProfileNow": { "message": "立即更新情景模式" }, + "options_guide_fixedProfileStep": { + "message": "代理情景包含了伺服器地址、埠等代理的資訊。
在 SwitchyOmega 中,情景模式是代理設定的基本單元。
默認設定中已經建立了一個代理情景模式作為樣例。試著開啟它吧。" + }, + "options_guide_fixedServersStep": { + "message": "在這裡,您可以填寫所需的代理伺服器地址和埠。
SwitchyOmega軟體本身不提供任何內建代理伺服器
如果您不清楚應該填寫什麼,最好諮詢下您的網路提供者,或者參考代理軟體的設定說明。" + }, + "options_guide_autoSwitchProfileStep": { + "message": "您可以通過強大的自動切換模式在多個代理間切換自如。
不過,在這個簡單的教程中無法詳盡介紹所有功能。
想要使用此功能時,可以開啟這裡的設定介面,來瞭解如何使用自動切換功能。" + }, + "options_guide_addMoreProfilesStep": { + "message": "如果您需要更多的情景模式,可以隨時在這裡創建代理、切換和其他情景模式
教程到此結束,您可以繼續自定義設定。" + }, + "options_guide_conditionStep": { + "message": "SwitchyOmega 可以根據切換條件對不同的網路請求使用不同的情景模式。
例如域名通配符條件可以對某個域名下的所有網址使用特定的情景模式。" + }, + "options_guide_conditionTypeStep": { + "message": "您可以使用各種條件類型來匹配域名或者整個網址。
點選問號按鈕來檢視條件類型的說明。" + }, + "options_guide_conditionProfileStep": { + "message": "對於任何匹配該條件的請求,SwitchyOmega 會使用這個情景模式。
如果選擇了\"[直接連線]\"情景模式,則匹配的請求不使用任何代理。" + }, + "options_guide_switchDefaultStep": { + "message": "如果請求不匹配任何條件,則使用默認情景模式。
條件的匹配順序總是按此頁面從上到下
您可以拖動排序圖示來更改條件的順序。" + }, + "options_guide_applySwitchProfileStep": { + "message": "當您設定完畢後,別忘記在彈出選單中啟用自動切換情景模式
圖示將會顯示標籤頁切換的最終結果情景。
懸停在圖示上則會顯示切換相關的詳細說明。" + }, "popup_externalProfile": { "message": "(外部情景模式)" }, @@ -682,18 +709,6 @@ "popup_addCondition": { "message": "添加條件" }, - "options_guide_fixedProfileStep": { - "message": "代理情景包含了伺服器地址、埠等代理的資訊。
在 SwitchyOmega 中,情景模式是代理設定的基本單元。
默認設定中已經建立了一個代理情景模式作為樣例。試著開啟它吧。" - }, - "options_guide_fixedServersStep": { - "message": "在這裡,您可以填寫所需的代理伺服器地址和埠。
SwitchyOmega軟體本身不提供任何內建代理伺服器
如果您不清楚應該填寫什麼,最好諮詢下您的網路提供者,或者參考代理軟體的設定說明。" - }, - "options_guide_autoSwitchProfileStep": { - "message": "您可以通過強大的自動切換模式在多個代理間切換自如。
不過,在這個簡單的教程中無法詳盡介紹所有功能。
想要使用此功能時,可以開啟這裡的設定介面,來瞭解如何使用自動切換功能。" - }, - "options_guide_addMoreProfilesStep": { - "message": "如果您需要更多的情景模式,可以隨時在這裡創建代理、切換和其他情景模式
教程到此結束,您可以繼續自定義設定。" - }, "popup_showOptions": { "message": "選項" }, diff --git a/omega-i18n/zh_TW/messages.json b/omega-i18n/zh_TW/messages.json index bf3310e..b53a8ab 100644 --- a/omega-i18n/zh_TW/messages.json +++ b/omega-i18n/zh_TW/messages.json @@ -658,6 +658,33 @@ "options_downloadProfileNow": { "message": "立即更新情景模式" }, + "options_guide_fixedProfileStep": { + "message": "代理情景包含了伺服器地址、埠等代理的資訊。
在 SwitchyOmega 中,情景模式是代理設定的基本單元。
默認設定中已經建立了一個代理情景模式作為樣例。試著開啟它吧。" + }, + "options_guide_fixedServersStep": { + "message": "在這裡,您可以填寫所需的代理伺服器地址和埠。
SwitchyOmega軟體本身不提供任何內建代理伺服器
如果您不清楚應該填寫什麼,最好諮詢下您的網路提供者,或者參考代理軟體的設定說明。" + }, + "options_guide_autoSwitchProfileStep": { + "message": "您可以通過強大的自動切換模式在多個代理間切換自如。
不過,在這個簡單的教程中無法詳盡介紹所有功能。
想要使用此功能時,可以開啟這裡的設定介面,來瞭解如何使用自動切換功能。" + }, + "options_guide_addMoreProfilesStep": { + "message": "如果您需要更多的情景模式,可以隨時在這裡創建代理、切換和其他情景模式
教程到此結束,您可以繼續自定義設定。" + }, + "options_guide_conditionStep": { + "message": "SwitchyOmega 可以根據切換條件對不同的網路請求使用不同的情景模式。
例如域名通配符條件可以對某個域名下的所有網址使用特定的情景模式。" + }, + "options_guide_conditionTypeStep": { + "message": "您可以使用各種條件類型來匹配域名或者整個網址。
點選問號按鈕來檢視條件類型的說明。" + }, + "options_guide_conditionProfileStep": { + "message": "對於任何匹配該條件的請求,SwitchyOmega 會使用這個情景模式。
如果選擇了\"[直接連線]\"情景模式,則匹配的請求不使用任何代理。" + }, + "options_guide_switchDefaultStep": { + "message": "如果請求不匹配任何條件,則使用默認情景模式。
條件的匹配順序總是按此頁面從上到下
您可以拖動排序圖示來更改條件的順序。" + }, + "options_guide_applySwitchProfileStep": { + "message": "當您設定完畢後,別忘記在彈出選單中啟用自動切換情景模式
圖示將會顯示標籤頁切換的最終結果情景。
懸停在圖示上則會顯示切換相關的詳細說明。" + }, "popup_externalProfile": { "message": "(外部情景模式)" }, @@ -682,18 +709,6 @@ "popup_addCondition": { "message": "添加條件" }, - "options_guide_fixedProfileStep": { - "message": "代理情景包含了伺服器地址、埠等代理的資訊。
在 SwitchyOmega 中,情景模式是代理設定的基本單元。
默認設定中已經建立了一個代理情景模式作為樣例。試著開啟它吧。" - }, - "options_guide_fixedServersStep": { - "message": "在這裡,您可以填寫所需的代理伺服器地址和埠。
SwitchyOmega軟體本身不提供任何內建代理伺服器
如果您不清楚應該填寫什麼,最好諮詢下您的網路提供者,或者參考代理軟體的設定說明。" - }, - "options_guide_autoSwitchProfileStep": { - "message": "您可以通過強大的自動切換模式在多個代理間切換自如。
不過,在這個簡單的教程中無法詳盡介紹所有功能。
想要使用此功能時,可以開啟這裡的設定介面,來瞭解如何使用自動切換功能。" - }, - "options_guide_addMoreProfilesStep": { - "message": "如果您需要更多的情景模式,可以隨時在這裡創建代理、切換和其他情景模式
教程到此結束,您可以繼續自定義設定。" - }, "popup_showOptions": { "message": "選項" }, diff --git a/omega-target/src/options.coffee b/omega-target/src/options.coffee index 377eab3..fed0414 100644 --- a/omega-target/src/options.coffee +++ b/omega-target/src/options.coffee @@ -57,7 +57,7 @@ class Options ).catch (ex) => @log.error(ex.stack) @reset().tap => - @_state.set({'firstRun': 'new'}) + @_state.set({'firstRun': 'new', 'web.switchGuide': 'showOnFirstUse'}) ).then((options) => @_options = options @_watch() diff --git a/omega-web/src/coffee/popup.coffee b/omega-web/src/coffee/popup.coffee index 79847f0..47ed0c2 100644 --- a/omega-web/src/coffee/popup.coffee +++ b/omega-web/src/coffee/popup.coffee @@ -45,9 +45,18 @@ module.controller 'PopupCtrl', ($scope, $window, $q, omegaTarget, $scope.openConditionHelp = -> pname = encodeURIComponent($scope.currentProfileName) $scope.openOptions("#/profile/#{pname}?help=condition") + $scope.applyProfile = (profile) -> - omegaTarget.applyProfile(profile.name).then -> - refresh() + omegaTarget.applyProfile(profile.name).then(-> + if refreshOnProfileChange + return omegaTarget.refreshActivePage() + ).then(-> + if profile.profileType == 'SwitchProfile' + return omegaTarget.state('web.switchGuide').then (switchGuide) -> + if switchGuide == 'showOnFirstUse' + return $scope.openOptions("#/profile/#{profile.name}") + ).then -> + $window.close() $scope.tempRuleMenu = {open: false} $scope.nameExternal = {open: false} diff --git a/omega-web/src/coffee/switch_profile_guide.coffee b/omega-web/src/coffee/switch_profile_guide.coffee new file mode 100644 index 0000000..f7fb466 --- /dev/null +++ b/omega-web/src/coffee/switch_profile_guide.coffee @@ -0,0 +1,74 @@ +$script 'lib/tether/tether.js', -> + $script 'lib/shepherd.js/shepherd.min.js', -> + tr = chrome.i18n.getMessage.bind(chrome.i18n) + tour = new Shepherd.Tour + defaults: + classes: 'shepherd-theme-arrows' + scrollTo: true + + tour.addStep 'condition-step', + text: tr('options_guide_conditionStep') + attachTo: '.switch-rule-row bottom' + scrollTo: true + buttons: [ + { + text: tr('options_guideSkip') + action: tour.cancel + classes: 'shepherd-button-secondary' + } + { + text: tr('options_guideNext') + action: tour.next + } + ] + + conditionTypeStep = tour.addStep('condition-type-step', + text: tr('options_guide_conditionTypeStep') + attachTo: '.condition-type-th bottom' + advanceOn: + selector: '.close-condition-help' + event: 'click' + scrollTo: true + buttons: [ + text: tr('options_guideNext') + action: tour.next + ] + ) + + conditionTypeStep.on 'show', -> + jQuery('.toggle-condition-help').one 'click', -> + return unless conditionTypeStep.isOpen() + jQuery('.shepherd-step.shepherd-enabled').hide() + jQuery('.toggle-condition-help, .close-condition-help').one 'click', -> + tour.next() + + tour.addStep 'condition-profile-step', + text: tr('options_guide_conditionProfileStep') + attachTo: '.switch-rule-row-target bottom' + scrollTo: true + buttons: [ + text: tr('options_guideNext') + action: tour.next + ] + + tour.addStep 'switch-default-step', + text: tr('options_guide_switchDefaultStep') + attachTo: '.switch-default-row top' + scrollTo: true + buttons: [ + text: tr('options_guideNext') + action: tour.next + ] + + tour.addStep 'apply-switch-profile-step', + text: tr('options_guide_applySwitchProfileStep') + attachTo: 'body top' + scrollTo: false + classes: 'shepherd-theme-arrows fixed-top-right' + buttons: [ + text: tr('options_guideDone') + action: tour.next + ] + + Shepherd.activeTour?.cancel() + tour.start() diff --git a/omega-web/src/less/options.less b/omega-web/src/less/options.less index 1ec6b0f..45a462a 100644 --- a/omega-web/src/less/options.less +++ b/omega-web/src/less/options.less @@ -80,6 +80,50 @@ ul.list-style-none, li.list-style-none { z-index: 10; } + .switch-rules { + position: relative; + background-color: #7f7f7f; + z-index: 11; + + &, th, td, tbody { + border-color: #6e6e6e !important; + } + + .btn { + opacity: .5; + } + + .form-control, .btn-default { + background-color: #7f7f7f; + border-color: #6e6e6e; + opacity: 1; + } + + .shepherd-enabled { + background-color: #fff; + border-color: #ddd !important; + &, td, tbody { + border-color: #ddd !important; + } + + .btn { + opacity: 1; + } + + .form-control, .btn-default { + background-color: #fff; + border-color: #ddd; + } + } + + } + + .condition-help-section { + position: relative; + z-index: 11; + background-color: #fff; + } + &:not([data-shepherd-step="fixed-servers-step"]) { .side-nav { position: absolute; @@ -92,6 +136,14 @@ ul.list-style-none, li.list-style-none { background-color: #fff; } } + + &[data-shepherd-step="switch-default-step"] { + .sort-bar { + position: relative; + z-index: 11; + background-color: #ffc; + } + } } .shepherd-enabled { @@ -103,6 +155,15 @@ ul.list-style-none, li.list-style-none { } } +.fixed-top-right { + position: fixed !important; + top: 0 !important; + right: 0 !important; + left: auto !important; + bottom: auto !important; + transform: none !important; +} + /* alert */ .alert-top-wrapper { diff --git a/omega-web/src/omega/controllers/switch_profile.coffee b/omega-web/src/omega/controllers/switch_profile.coffee index 9a55d0e..97c3a50 100644 --- a/omega-web/src/omega/controllers/switch_profile.coffee +++ b/omega-web/src/omega/controllers/switch_profile.coffee @@ -1,5 +1,5 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location, - $modal, profileIcons, getAttachedName) -> + $modal, profileIcons, getAttachedName, omegaTarget) -> $scope.showConditionHelp = ($location.search().help == 'condition') @@ -212,3 +212,12 @@ angular.module('omega').controller 'SwitchProfileCtrl', ($scope, $location, ).result.then -> $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') diff --git a/omega-web/src/partials/profile_switch.jade b/omega-web/src/partials/profile_switch.jade index 48c64e7..45eb4d6 100644 --- a/omega-web/src/partials/profile_switch.jade +++ b/omega-web/src/partials/profile_switch.jade @@ -1,5 +1,5 @@ div(ng-controller='SwitchProfileCtrl') - section.settings-group(ng-show='showConditionHelp' ng-init='expandedSection = {id: 0}') + section.condition-help-section.settings-group(ng-show='showConditionHelp' ng-init='expandedSection = {id: 0}') h3 | {{'options_group_conditionHelp' | tr}} button.close.close-condition-help(type='button' ng-click='showConditionHelp = false') @@ -16,22 +16,23 @@ div(ng-controller='SwitchProfileCtrl') dd(ng-repeat-end ng-bind-html='"condition_help_" + type | tr') section.settings-group h3 {{'options_group_switchRules' | tr}} - .table-responsive + .table-responsive.switch-rules-wrapper table.switch-rules.table.table-bordered.table-condensed.width-limit-xl thead tr th(style='white-space: nowrap') {{'options_sort' | tr}} - th + th.condition-type-th | {{'options_conditionType' | tr}} = ' ' - button.btn.btn-link.btn-sm.clear-padding(title='{{"options_showConditionTypeHelp" | tr}}' + button.btn.btn-link.btn-sm.clear-padding.toggle-condition-help( + title='{{"options_showConditionTypeHelp" | tr}}' ng-click='showConditionHelp = !showConditionHelp') span.glyphicon.glyphicon-question-sign th {{'options_conditionDetails' | tr}} th {{'options_resultProfile' | tr}} th {{'options_conditionActions' | tr}} tbody(ui-sortable='sortableOptions' ng-model='profile.rules') - tr(ng-repeat='rule in profile.rules') + tr.switch-rule-row(ng-repeat='rule in profile.rules') td.sort-bar span.glyphicon.glyphicon-sort td @@ -50,7 +51,7 @@ div(ng-controller='SwitchProfileCtrl') input.form-control(type='number' max='99' min='1' ng-model='rule.condition.maxValue' required) input.form-control(ng-model='rule.condition.pattern' ng-switch-default required ui-validate='{pattern: "validateCondition(rule.condition, $value)"}') - td + td.switch-rule-row-target div(omega-profile-select='options | profiles:profile' ng-model='rule.profileName' disp-name='dispNameFilter' options='options' ng-class='{disabled: rule.condition.conditionType == "NeverCondition"}') @@ -86,7 +87,7 @@ div(ng-controller='SwitchProfileCtrl') button.btn.btn-danger.btn-sm(title="{{'options_deleteAttached' | tr}}" ng-click='removeAttached()') span.glyphicon.glyphicon-trash tbody - tr + tr.switch-default-row td td(colspan='2') {{'options_switchDefaultProfile' | tr}} td