Update top nav input box action button icon depends on input (#1738)

* Rename `showArrow` to `showActionButton`

* * Display different icon for action button when input text look like a Youtube URL

* ! Fix transition for button appearing absent

* * Update to use new icon for all FT supported URLs

* Update src/renderer/components/ft-input/ft-input.js

Co-authored-by: Jason <84899178+jasonhenriquez@users.noreply.github.com>

* * Update action button to look disabled when input text is empty

* * Disable button hover/active visual effect when "disabled"

* * Make action button only respond to cursor when enabled

Co-authored-by: Jason <84899178+jasonhenriquez@users.noreply.github.com>
This commit is contained in:
PikachuEXE 2021-10-01 15:38:33 +08:00 committed by GitHub
parent 7d0880ad05
commit 87e1093c4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 104 additions and 26 deletions

View File

@ -33,7 +33,7 @@
>
<ft-input
:placeholder="$t('Settings.External Player Settings.Custom External Player Executable')"
:show-arrow="false"
:show-action-button="false"
:show-label="true"
:value="externalPlayerExecutable"
:tooltip="$t('Tooltips.External Player Settings.Custom External Player Executable')"
@ -41,7 +41,7 @@
/>
<ft-input
:placeholder="$t('Settings.External Player Settings.Custom External Player Arguments')"
:show-arrow="false"
:show-action-button="false"
:show-label="true"
:value="externalPlayerCustomArgs"
:tooltip="$t('Tooltips.External Player Settings.Custom External Player Arguments')"

View File

@ -90,10 +90,17 @@
position: absolute;
padding: 10px 8px;
top: 5px;
right: 0px;
cursor: pointer;
right: 0;
border-radius: 200px 200px 200px 200px;
color: var(--primary-text-color);
/* this should look disabled by default */
opacity: 50%;
}
.inputAction.enabled {
opacity: 100%;
/* Only look respond to cursor when enabled */
cursor: pointer;
}
.search ::-webkit-calendar-picker-indicator {
@ -108,7 +115,7 @@
color: #EEEEEE;
}
.ft-input-component.showArrow .ft-input {
.ft-input-component.showActionButton .ft-input {
/*
With arrow present means
the text might get under the arrow with normal padding
@ -116,25 +123,25 @@
padding-right: 2em;
}
.inputAction:hover {
.inputAction.enabled:hover {
background-color: var(--side-nav-hover-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}
.forceTextColor .inputAction:hover {
.forceTextColor .inputAction.enabled:hover {
background-color: var(--primary-color-hover);
}
.inputAction:active {
.inputAction.enabled:active {
background-color: var(--tertiary-text-color);
-moz-transition: background 0.2s ease-in;
-o-transition: background 0.2s ease-in;
transition: background 0.2s ease-in;
}
.forceTextColor .inputAction:active {
.forceTextColor .inputAction.enabled:active {
background-color: var(--primary-color-active);
}

View File

@ -1,5 +1,6 @@
import Vue from 'vue'
import FtTooltip from '../ft-tooltip/ft-tooltip.vue'
import { mapActions } from 'vuex'
export default Vue.extend({
name: 'FtInput',
@ -15,7 +16,7 @@ export default Vue.extend({
type: String,
default: ''
},
showArrow: {
showActionButton: {
type: Boolean,
default: true
},
@ -63,7 +64,9 @@ export default Vue.extend({
},
// This button should be invisible on app start
// As the text input box should be empty
clearTextButtonVisible: false
clearTextButtonExisting: false,
clearTextButtonVisible: false,
actionButtonIconName: 'search'
}
},
computed: {
@ -91,12 +94,19 @@ export default Vue.extend({
if (newVal) {
// The button needs to be visible **immediately**
// To allow user to see the transition
this.clearTextButtonVisible = true
this.clearTextButtonExisting = true
// The transition is not rendered if this property is set right after
// It's visible
setTimeout(() => {
this.clearTextButtonVisible = true
}, 0)
} else {
// Hide the button after the transition
// Hide the button with transition
this.clearTextButtonVisible = false
// Remove the button after the transition
// 0.2s in CSS = 200ms in JS
setTimeout(() => {
this.clearTextButtonVisible = false
this.clearTextButtonExisting = false
}, 200)
}
}
@ -109,6 +119,9 @@ export default Vue.extend({
},
methods: {
handleClick: function () {
// No action if no input text
if (!this.inputDataPresent) { return }
this.searchState.showOptions = false
this.$emit('input', this.inputData)
this.$emit('click', this.inputData)
@ -118,11 +131,13 @@ export default Vue.extend({
if (this.isSearch &&
this.searchState.selectedOption !== -1 &&
this.inputData === this.dataList[this.searchState.selectedOption]) { return }
this.handleActionIconChange()
this.$emit('input', this.inputData)
},
handleClearTextClick: function () {
this.inputData = ''
this.handleActionIconChange()
this.$emit('input', this.inputData)
// Focus on input element after text is clear for better UX
@ -130,6 +145,55 @@ export default Vue.extend({
inputElement.focus()
},
handleActionIconChange: function() {
// Only need to update icon if visible
if (!this.showActionButton) { return }
if (!this.inputDataPresent) {
// Change back to default icon if text is blank
this.actionButtonIconName = 'search'
return
}
// Update action button icon according to input
try {
this.getYoutubeUrlInfo(this.inputData).then((result) => {
let isYoutubeLink = false
switch (result.urlType) {
case 'video':
case 'playlist':
case 'search':
case 'channel':
isYoutubeLink = true
break
case 'hashtag':
// TODO: Implement a hashtag related view
// isYoutubeLink is already `false`
break
case 'invalid_url':
default: {
// isYoutubeLink is already `false`
}
}
if (isYoutubeLink) {
// Go to URL (i.e. Video/Playlist/Channel
this.actionButtonIconName = 'arrow-right'
} else {
// Search with text
this.actionButtonIconName = 'search'
}
})
} catch (ex) {
// On exception, consider text as invalid URL
this.actionButtonIconName = 'search'
// Rethrow exception
throw ex
}
},
addListener: function () {
const inputElement = document.getElementById(this.id)
@ -178,6 +242,10 @@ export default Vue.extend({
if (this.selectOnFocus) {
e.target.select()
}
}
},
...mapActions([
'getYoutubeUrlInfo'
])
}
})

View File

@ -4,7 +4,7 @@
:class="{
search: isSearch,
forceTextColor: forceTextColor,
showArrow: showArrow,
showActionButton: showActionButton,
showClearTextButton: showClearTextButton
}"
>
@ -21,11 +21,11 @@
/>
</label>
<font-awesome-icon
v-if="showClearTextButton && clearTextButtonVisible"
v-if="showClearTextButton && clearTextButtonExisting"
icon="times-circle"
class="clearInputTextButton"
:class="{
visible: inputDataPresent
visible: clearTextButtonVisible
}"
tabindex="0"
role="button"
@ -49,9 +49,12 @@
@keydown="e => handleKeyDown(e.keyCode)"
>
<font-awesome-icon
v-if="showArrow"
icon="arrow-right"
v-if="showActionButton"
:icon="actionButtonIconName"
class="inputAction"
:class="{
enabled: inputDataPresent
}"
@click="handleClick"
/>

View File

@ -7,7 +7,7 @@
class="profileName"
placeholder="Profile Name"
:value="profileName"
:show-arrow="false"
:show-action-button="false"
@input="e => profileName = e"
/>
</ft-flex-box>
@ -40,7 +40,7 @@
class="profileName"
placeholder=""
:value="profileBgColor"
:show-arrow="false"
:show-action-button="false"
:disabled="true"
/>
</ft-flex-box>

View File

@ -96,7 +96,7 @@
<ft-flex-box class="generalSettingsFlexBox">
<ft-input
:placeholder="$t('Settings.General Settings.Current Invidious Instance')"
:show-arrow="false"
:show-action-button="false"
:show-label="true"
:value="currentInvidiousInstance"
:data-list="invidiousInstancesList"

View File

@ -25,14 +25,14 @@
<ft-flex-box>
<ft-input
:placeholder="$t('Settings.Proxy Settings.Proxy Host')"
:show-arrow="false"
:show-action-button="false"
:show-label="true"
:value="proxyHostname"
@input="handleUpdateProxyHostname"
/>
<ft-input
:placeholder="$t('Settings.Proxy Settings.Proxy Port Number')"
:show-arrow="false"
:show-action-button="false"
:show-label="true"
:value="proxyPort"
@input="handleUpdateProxyPort"

View File

@ -23,7 +23,7 @@
<ft-flex-box>
<ft-input
:placeholder="$t('Settings.SponsorBlock Settings[\'SponsorBlock API Url (Default is https://sponsor.ajay.app)\']')"
:show-arrow="false"
:show-action-button="false"
:show-label="true"
:value="sponsorBlockUrl"
@input="handleUpdateSponsorBlockUrl"