feat: add message to add to home screen on mobile

This commit is contained in:
kolaente 2023-06-12 19:37:58 +02:00
parent 169feaaf0f
commit 3c9083b90d
Signed by untrusted user: konrad
GPG Key ID: F40E70337AB24C9B
6 changed files with 102 additions and 7 deletions

View File

@ -12,6 +12,7 @@
<keyboard-shortcuts v-if="keyboardShortcutsActive"/>
<Teleport to="body">
<AddToHomeScreen/>
<UpdateNotification/>
<Notification/>
</Teleport>
@ -43,6 +44,7 @@ import {useBaseStore} from '@/stores/base'
import {useColorScheme} from '@/composables/useColorScheme'
import {useBodyClass} from '@/composables/useBodyClass'
import AddToHomeScreen from '@/components/home/AddToHomeScreen.vue'
const baseStore = useBaseStore()
const authStore = useAuthStore()

View File

@ -0,0 +1,80 @@
<template>
<div
v-if="shouldShowMessage"
class="add-to-home-screen"
:class="{'has-update-available': hasUpdateAvailable}"
>
<icon icon="arrow-up-from-bracket" class="add-icon"/>
<p>
{{ $t('home.addToHomeScreen') }}
</p>
<BaseButton @click="() => hideMessage = true" class="hide-button">
<icon icon="x"/>
</BaseButton>
</div>
</template>
<script lang="ts" setup>
import BaseButton from '@/components/base/BaseButton.vue'
import {useLocalStorage} from '@vueuse/core'
import {computed} from 'vue'
import {useBaseStore} from '@/stores/base'
const baseStore = useBaseStore()
const hideMessage = useLocalStorage('hideAddToHomeScreenMessage', false)
const hasUpdateAvailable = computed(() => baseStore.updateAvailable)
const shouldShowMessage = computed(() => {
if (hideMessage.value) {
return false
}
if (typeof window !== 'undefined' && window.matchMedia('(display-mode: standalone)').matches) {
return false
}
return true
})
</script>
<style lang="scss" scoped>
.add-to-home-screen {
position: fixed;
// FIXME: We should prevent usage of z-index or
// at least define it centrally
// the highest z-index of a modal is .hint-modal with 4500
z-index: 5000;
bottom: 1rem;
inset-inline: 1rem;
max-width: max-content;
margin-inline: auto;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
padding: .5rem 1rem;
background: var(--grey-900);
border-radius: $radius;
font-size: .9rem;
color: var(--grey-200);
@media screen and (min-width: $tablet) {
display: none;
}
&.has-update-available {
bottom: 5rem;
}
}
.add-icon {
color: var(--primary-light);
}
.hide-button {
padding: .25rem .5rem;
cursor: pointer;
}
</style>

View File

@ -12,9 +12,12 @@
</template>
<script lang="ts" setup>
import {ref} from 'vue'
import {computed, ref} from 'vue'
import {useBaseStore} from '@/stores/base'
const updateAvailable = ref(false)
const baseStore = useBaseStore()
const updateAvailable = computed(() => baseStore.updateAvailable)
const registration = ref(null)
const refreshing = ref(false)
@ -31,11 +34,11 @@ navigator?.serviceWorker?.addEventListener(
function showRefreshUI(e: Event) {
console.log('recieved refresh event', e)
registration.value = e.detail
updateAvailable.value = true
baseStore.setUpdateAvailable(true)
}
function refreshApp() {
updateAvailable.value = false
baseStore.setUpdateAvailable(false)
if (!registration.value || !registration.value.waiting) {
return
}
@ -65,7 +68,6 @@ function refreshApp() {
border-radius: $radius;
font-size: .9rem;
color: var(--grey-900);
}
.update-notification__message {

View File

@ -4,6 +4,7 @@ import {
faAngleRight,
faArchive,
faArrowLeft,
faArrowUpFromBracket,
faBars,
faBell,
faCalendar,
@ -56,7 +57,7 @@ import {
faTimes,
faTrashAlt,
faUser,
faUsers,
faUsers, faX,
} from '@fortawesome/free-solid-svg-icons'
import {
faBellSlash,
@ -71,7 +72,7 @@ import {
} from '@fortawesome/free-regular-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'
import type { FontAwesomeIcon as FontAwesomeIconFixedTypes } from '@/types/vue-fontawesome'
import type {FontAwesomeIcon as FontAwesomeIconFixedTypes} from '@/types/vue-fontawesome'
library.add(faAlignLeft)
library.add(faAngleRight)
@ -139,6 +140,8 @@ library.add(faTimesCircle)
library.add(faTrashAlt)
library.add(faUser)
library.add(faUsers)
library.add(faArrowUpFromBracket)
library.add(faX)
// overwriting the wrong types
export default FontAwesomeIcon as unknown as FontAwesomeIconFixedTypes

View File

@ -5,6 +5,7 @@
"welcomeDay": "Hi {username}!",
"welcomeEvening": "Good Evening {username}!",
"lastViewed": "Last viewed",
"addToHomeScreen": "Add this app to your home screen for faster access and improved experience.",
"project": {
"importText": "Import your projects and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"

View File

@ -28,6 +28,7 @@ export const useBaseStore = defineStore('base', () => {
const keyboardShortcutsActive = ref(false)
const quickActionsActive = ref(false)
const logoVisible = ref(true)
const updateAvailable = ref(false)
function setLoading(newLoading: boolean) {
loading.value = newLoading
@ -77,6 +78,10 @@ export const useBaseStore = defineStore('base', () => {
function setReady(value: boolean) {
ready.value = value
}
function setUpdateAvailable(value: boolean) {
updateAvailable.value = value
}
async function handleSetCurrentProject(
{project, forceUpdate = false}: {project: IProject | null, forceUpdate?: boolean},
@ -135,6 +140,7 @@ export const useBaseStore = defineStore('base', () => {
keyboardShortcutsActive: readonly(keyboardShortcutsActive),
quickActionsActive: readonly(quickActionsActive),
logoVisible: readonly(logoVisible),
updateAvailable: readonly(updateAvailable),
setLoading,
setReady,
@ -145,6 +151,7 @@ export const useBaseStore = defineStore('base', () => {
setBackground,
setBlurHash,
setLogoVisible,
setUpdateAvailable,
handleSetCurrentProject,
loadApp,