Skip to content

Commit

Permalink
Merge pull request #62 from evandor/TAB-435-toasts
Browse files Browse the repository at this point in the history
Tab 435 toasts
  • Loading branch information
evandor authored Nov 7, 2023
2 parents 3c310b0 + 53868da commit e490a68
Show file tree
Hide file tree
Showing 12 changed files with 663 additions and 460 deletions.
144 changes: 88 additions & 56 deletions src/components/SidePanelFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,37 @@

<q-footer class="bg-white q-pa-xs q-mt-sm" style="border-top: 1px solid lightgrey">
<div class="row fit">
<div class="col-8">

<template v-if="showSuggestionButton">
<q-btn
outline
icon="o_lightbulb"
:label="suggestionsLabel()"
:color="dependingOnStates()"
@click="suggestionDialog()"
class="q-ma-none q-pa-xs q-ml-sm q-mt-xs q-pr-md cursor-pointer"
size="10px">
</q-btn>

</template>
<div class="col-9">

<Transition name="fade" appear>
<q-banner
v-if="checkToasts()"
inline-actions dense rounded
style="font-size: smaller"
:class="toastBannerClass()">
{{ useUiStore().toasts[0]?.msg }}
<template v-slot:action v-if="useUiStore().toasts[0]?.action">
<q-btn flat label="Undo"
@click="useUiStore().callUndoActionFromCurrentToast()"/>
</template>
</q-banner>
</Transition>

<q-btn v-if="!checkToasts() && !transitionGraceTime && showSuggestionButton"
outline
icon="o_lightbulb"
:label="suggestionsLabel()"
:color="dependingOnStates()"
@click="suggestionDialog()"
class="q-ma-none q-pa-xs q-ml-sm q-mt-xs q-pr-md cursor-pointer"
size="10px">
</q-btn>

<template v-else>
<template v-if="!checkToasts() && !transitionGraceTime && !showSuggestionButton">

<q-btn v-if="showSuggestionIcon"
@click="doShowSuggestionButton = true"
icon="o_lightbulb"
class="q-my-xs q-ml-xs q-px-xs"
flat
color="warning"
size="9px">
<q-tooltip class="tooltip">{{ suggestionsLabel() }}</q-tooltip>
</q-btn>

<SidePanelFooterLeftButton
:side-panel-view="SidePanelView.TABS_LIST" icon="o_playlist_add"
tooltip="All your browser's open tabs"/>

<SidePanelFooterLeftButton :side-panel-view="SidePanelView.BOOKMARKS" icon="o_bookmark"
tooltip="Show the Bookmarks Browser"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.TAGS_LIST" icon="o_label"
tooltip="List of all tags sorted by prevalence"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.BY_DOMAIN_LIST" icon="o_dns"
tooltip="List all your tabs URLs by domain"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.RSS_LIST" icon="o_rss_feed"
tooltip="List all your RSS feeds"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.NEWEST_TABS_LIST" icon="o_schedule"
tooltip="Newest Tabs List"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.TOP_10_TABS_LIST" icon="o_workspace_premium"
tooltip="Top 10 Tabs List"/>

<span class="q-ma-none"
v-if="permissionsStore.hasFeature(FeatureIdent.OPENTABS_THRESHOLD) && tabsStore.tabsets?.size > 0">
<OpenTabsThresholdWidget :showLabel="false" :in-side-panel="true">
<q-tooltip>{{ tabsStore.tabs?.length }} open tabs</q-tooltip>
</OpenTabsThresholdWidget>
</span>
<SidePanelFooterLeftButtons
@was-clicked="doShowSuggestionButton = true"
:show-suggestion-icon="showSuggestionIcon"/>

</template>

Expand All @@ -74,15 +55,15 @@
:class="rightButtonClass()"
flat
color="black"
size="8px"
:size="getButtonSize()"
@click="openHelpView()">
</q-btn>

<q-btn icon="o_settings"
:class="rightButtonClass()"
flat
color="black"
size="8px"
:size="getButtonSize()"
@click="openOptionsPage()">
<q-tooltip class="tooltip" anchor="top left" self="bottom left">{{ settingsTooltip() }}</q-tooltip>
</q-btn>
Expand All @@ -93,7 +74,7 @@
:class="rightButtonClass()"
flat
color="black"
size="8px"
:size="getButtonSize()"
@click="openExtensionTab()">
<q-tooltip class="tooltip">Tabsets as full-page app</q-tooltip>
</q-btn>
Expand All @@ -111,9 +92,7 @@ import {ref, watchEffect} from "vue";
import {useRouter} from "vue-router";
import {usePermissionsStore} from "src/stores/permissionsStore";
import {FeatureIdent} from "src/models/AppFeature";
import OpenTabsThresholdWidget from "components/widgets/OpenTabsThresholdWidget.vue";
import NavigationService from "src/services/NavigationService";
import SidePanelFooterLeftButton from "components/helper/SidePanelFooterLeftButton.vue";
import {useQuasar} from "quasar";
import {useUtils} from "src/services/Utils";
import {useWindowsStore} from "src/stores/windowsStore";
Expand All @@ -122,13 +101,13 @@ import _ from "lodash";
import {SuggestionState, SuggestionType} from "src/models/Suggestion";
import SuggestionDialog from "components/dialogues/SuggestionDialog.vue";
import {TabsetStatus} from "src/models/Tabset";
import {ToastType} from "src/models/Toast";
import SidePanelFooterLeftButtons from "components/helper/SidePanelFooterLeftButtons.vue";
const {inBexMode} = useUtils()
const $q = useQuasar()
const tabsStore = useTabsStore()
const permissionsStore = usePermissionsStore()
const router = useRouter()
const uiStore = useUiStore()
Expand All @@ -140,10 +119,11 @@ const progressLabel = ref<string | undefined>(undefined)
const showSuggestionButton = ref(false)
const showSuggestionIcon = ref(false)
const doShowSuggestionButton = ref(false)
const transitionGraceTime = ref(false)
watchEffect(() => {
const suggestions = useSuggestionsStore().getSuggestions()
//console.log("watcheffect for", suggestions)
console.log("watcheffect for", suggestions)
showSuggestionButton.value =
doShowSuggestionButton.value ||
(useUiStore().sidePanelActiveViewIs(SidePanelView.MAIN) &&
Expand Down Expand Up @@ -233,4 +213,56 @@ const openHelpView = () => {
}
}
const checkToasts = () => {
if (useUiStore().toasts.length > 0) {
const useDelay = 3000
useUiStore().delayedToastRemoval(useDelay)
const oldShowButton = showSuggestionButton.value
const oldDoShowButton = doShowSuggestionButton.value
transitionGraceTime.value = true
showSuggestionButton.value = false
doShowSuggestionButton.value = false
setTimeout(() => {
console.log(" *** ", useUiStore().toasts.length)
if (useUiStore().toasts.length === 0) { // only if all toasts are gone
transitionGraceTime.value = false
showSuggestionButton.value = oldShowButton
doShowSuggestionButton.value = oldDoShowButton
}
}, useDelay + 1100) // must be higher than css value in fade-leave-active
return true
}
return false
}
const getButtonSize = () => useUiStore().getButtonSize('sidePanelFooter')
const toastBannerClass = () => {
const defaults = " text-white q-py-none"
switch (useUiStore().toasts[0]?.type) {
case ToastType.INFO:
return "bg-positive" + defaults
case ToastType.WARNING:
return "bg-warning" + defaults
case ToastType.ERROR:
return "bg-negative" + defaults
default:
return "bg-negative" + defaults
}
}
</script>

<style>
.fade-enter-active {
transition: opacity 0.5s ease;
}
.fade-leave-active {
transition: opacity 1.0s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
6 changes: 4 additions & 2 deletions src/components/helper/SidePanelFooterLeftButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
:class="leftButtonClass()"
flat
:color="isActive() ? 'secondary':'black'"
size="9px"
:size="props.size"
@click="toggleView()">
<q-tooltip v-if="props.tooltip"
:delay="700"
Expand All @@ -22,6 +22,7 @@ import {useRouter} from "vue-router";
const props = defineProps({
sidePanelView: {type: Object as PropType<SidePanelView>, required: true},
icon: {type: String, required: true},
size: {type: String, default: "9px"},
tooltip: {type: String, required: false}
})
Expand All @@ -31,7 +32,7 @@ const isActive = () => useUiStore().sidePanelIsActive(props.sidePanelView)
const activateView = (view: SidePanelView) => useUiStore().sidePanelSetActiveView(view)
const showButton = () => props.sidePanelView?.showButton()
const leftButtonClass = () => "q-my-xs q-ml-xs q-px-xs"
const leftButtonClass = () => "q-my-xs q-ml-xs q-mr-none q-px-xs"
const toggleView = () => {
if (isActive()) {
Expand All @@ -43,4 +44,5 @@ const toggleView = () => {
}
}
</script>
82 changes: 82 additions & 0 deletions src/components/helper/SidePanelFooterLeftButtons.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>

<q-btn v-if="props.showSuggestionIcon"
@click.stop="emits('wasClicked')"
icon="o_lightbulb"
class="q-my-xs q-ml-xs q-px-xs"
flat
color="warning"
size="9px">
<q-tooltip class="tooltip">{{ suggestionsLabel() }}</q-tooltip>
</q-btn>

<SidePanelFooterLeftButton
:side-panel-view="SidePanelView.TABS_LIST" icon="o_playlist_add"
tooltip="All your browser's open tabs"/>

<SidePanelFooterLeftButton :side-panel-view="SidePanelView.BOOKMARKS"
icon="bookmark"
:size="buttonSize"
tooltip="Show the Bookmarks Browser"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.TAGS_LIST"
icon="o_label"
:size="buttonSize"
tooltip="List of all tags sorted by prevalence"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.BY_DOMAIN_LIST"
icon="o_dns"
:size="buttonSize"
tooltip="List all your tabs URLs by domain"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.RSS_LIST"
icon="o_rss_feed"
tooltip="List all your RSS feeds"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.NEWEST_TABS_LIST"
icon="o_schedule"
:size="buttonSize"
tooltip="Newest Tabs List"/>
<SidePanelFooterLeftButton :side-panel-view="SidePanelView.TOP_10_TABS_LIST"
icon="o_workspace_premium"
:size="buttonSize"
tooltip="Top 10 Tabs List"/>

<span class="q-ma-none"
v-if="permissionsStore.hasFeature(FeatureIdent.OPENTABS_THRESHOLD) && tabsStore.tabsets?.size > 0">
<OpenTabsThresholdWidget :showLabel="false" :in-side-panel="true">
<q-tooltip>{{ tabsStore.tabs?.length }} open tabs</q-tooltip>
</OpenTabsThresholdWidget>
</span>

</template>
<script setup lang="ts">
import {SidePanelView, useUiStore} from "stores/uiStore";
import {FeatureIdent} from "src/models/AppFeature";
import SidePanelFooterLeftButton from "components/helper/SidePanelFooterLeftButton.vue";
import OpenTabsThresholdWidget from "components/widgets/OpenTabsThresholdWidget.vue";
import {usePermissionsStore} from "stores/permissionsStore";
import {useTabsStore} from "stores/tabsStore";
import {useSuggestionsStore} from "stores/suggestionsStore";
import {ref, watchEffect} from "vue";
const props = defineProps({
showSuggestionIcon: {type: Boolean, required: true}
})
const emits = defineEmits(['wasClicked'])
const permissionsStore = usePermissionsStore()
const tabsStore = useTabsStore()
const buttonSize = ref('15px')
watchEffect(() => {
buttonSize.value = useUiStore().getButtonSize('sidePanelFooter')
})
const suggestionsLabel = () => {
const suggestions = useSuggestionsStore().getSuggestions()
return suggestions.length === 1 ?
suggestions.length + " New Suggestion" :
suggestions.length + " New Suggestions"
}
</script>
4 changes: 2 additions & 2 deletions src/domain/tabsets/CreateTabset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {useWindowsStore} from "src/stores/windowsStore";
import {STRIP_CHARS_IN_USER_INPUT} from "boot/constants";
import {TabsetType} from "src/models/Tabset";

const {inBexMode, sendMsg} = useUtils()
const {sendMsg} = useUtils()

class UndoCreateTabsetCommand implements Command<object> {

Expand Down Expand Up @@ -69,7 +69,7 @@ export class CreateTabsetCommand implements Command<SaveOrReplaceResult> {
return res
}
)
let doneMsg = 'Tabset \'' + this.tabsetName + '\' created successfully'
let doneMsg = 'Tabset created'
if (result['replaced' as keyof object] && result['merged' as keyof object]) {
doneMsg = 'Existing Tabset \'' + this.tabsetName + '\' can be updated now'
} else if (result['replaced' as keyof object]) {
Expand Down
4 changes: 1 addition & 3 deletions src/domain/tabsets/DeleteTabset.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Command from "src/domain/Command";
import {ExecutionResult} from "src/domain/ExecutionResult";
import {useTabsetService} from "src/services/TabsetService2";
import {useUtils} from "src/services/Utils";

export class DeleteTabsetCommand implements Command<string> {

Expand All @@ -14,8 +13,7 @@ export class DeleteTabsetCommand implements Command<string> {
//sendMsg('tabset-deleted', {tabsetId: this.tabsetId})
return res
})

.then(res => Promise.resolve(new ExecutionResult(res, "Tabset was deleted")))
.then(res => Promise.resolve(new ExecutionResult(res, "Tabset deleted")))
.catch(err => Promise.reject(err))
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/domain/tabsets/MarkTabsetDeleted.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class MarkTabsetDeletedCommand implements Command<Tabset> {
.then(res => Promise.resolve(
new ExecutionResult(
res,
"Tabset was deleted",
"Tabset deleted",
new UndoCommand(this.tabsetId)))
)
.catch(err => Promise.reject(err))
Expand Down
20 changes: 20 additions & 0 deletions src/models/Toast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {uid} from "quasar";

export enum ToastType {
INFO = "INFO",
WARNING = "WARNING",
ERROR = "ERROR"
}

export class Toast {

public id: string
public created: number;

constructor(
public msg: string, public type: ToastType, public action: any = undefined) {
this.id = uid()
this.created = new Date().getTime()
}

}
Loading

0 comments on commit e490a68

Please sign in to comment.