Refactor navigator utility functions and add isPWA check

This commit is contained in:
jxxghp
2024-10-19 10:39:31 +08:00
parent b3f616ddc6
commit 76a487854b
16 changed files with 38 additions and 82 deletions

View File

@@ -2,8 +2,7 @@
export async function getClipboardContent() {
if (navigator.clipboard && window.isSecureContext) {
return await navigator.clipboard.readText()
}
else {
} else {
const input = document.createElement('textarea')
document.body.appendChild(input)
input.select()
@@ -18,8 +17,7 @@ export async function getClipboardContent() {
export async function copyToClipboard(content: string) {
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(content)
}
else {
} else {
const input = document.createElement('textarea')
input.value = content
document.body.appendChild(input)
@@ -42,3 +40,12 @@ export function urlBase64ToUint8Array(base64String: string) {
}
return outputArray
}
// 判断是否为PWA
export const isPWA = async (): Promise<boolean> => {
if ('serviceWorker' in navigator) {
const registrations = await navigator.serviceWorker.getRegistrations()
return registrations.length > 0
}
return (window.navigator as any).standalone === true
}

View File

@@ -92,7 +92,9 @@ const canEditUser = computed(() => {
// 计算是否有用户管理权限
const canManageUser = computed(() => {
return canEditUser
if (props.user.name == currentLoginUser) return false
if (store.state.auth.superUser) return true
return false
})
// 用户重新完成时

View File

@@ -63,7 +63,7 @@ const userForm = ref<User>({
name: props.username ?? '',
password: '',
email: '',
is_active: false,
is_active: true,
is_superuser: false,
avatar: avatar1,
is_otp: false,

View File

@@ -15,9 +15,7 @@ import { useDisplay } from 'vuetify'
const display = useDisplay()
// APP
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 输入参数
const inProps = defineProps({
@@ -119,7 +117,7 @@ const currentImgLink = ref('')
// 大小控制
const scrollStyle = computed(() => {
return appMode.value
return appMode
? 'height: calc(100vh - 15.5rem - env(safe-area-inset-bottom) - 3.5rem)'
: 'height: calc(100vh - 14.5rem - env(safe-area-inset-bottom)'
})

View File

@@ -14,9 +14,7 @@ import { NavMenu } from '@/@layouts/types'
import { useDisplay } from 'vuetify'
const display = useDisplay()
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 是否超级用户
let superUser = store.state.auth.superUser

View File

@@ -1,10 +1,5 @@
<script setup lang="ts">
import { useDisplay } from 'vuetify'
const display = useDisplay()
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
const route = useRoute()

View File

@@ -59,20 +59,10 @@ async function restart() {
}
}
// 是否精简模式
const isCompactMode = ref(localStorage.getItem('MP_APPMODE') != '0')
// 从Vuex Store中获取信息
const superUser = computed(() =>store.state.auth.superUser)
const userName = computed(() =>store.state.auth.userName)
const superUser = computed(() => store.state.auth.superUser)
const userName = computed(() => store.state.auth.userName)
const avatar = computed(() => store.state.auth.avatar || avatar1)
// 监听精简模式切换
watch(isCompactMode, value => {
localStorage.setItem('MP_APPMODE', value ? '1' : '0')
//刷新页面
location.reload()
})
</script>
<template>
@@ -97,16 +87,6 @@ watch(isCompactMode, value => {
<VListItemSubtitle>{{ userName }}</VListItemSubtitle>
</VListItem>
<!-- Divider -->
<VDivider v-if="display.mdAndDown.value" class="my-2" />
<!-- 👉 AppMode -->
<VListItem v-if="display.mdAndDown.value">
<template #prepend>
<VSwitch class="me-2" v-model="isCompactMode"></VSwitch>
</template>
<VListItemTitle>App模式</VListItemTitle>
</VListItem>
<VDivider class="my-2" />
<!-- 👉 Profile -->

View File

@@ -23,20 +23,24 @@ import MediaInfoCard from './components/cards/MediaInfoCard.vue'
import TorrentCard from './components/cards/TorrentCard.vue'
import MediaIdSelector from './components/misc/MediaIdSelector.vue'
import PathField from './components/input/PathField.vue'
import { fetchGlobalSettings } from './api'
import { isPWA } from './@core/utils/navigator'
import '@core/scss/template/index.scss'
import '@layouts/styles/index.scss'
import '@styles/styles.scss'
import 'vue-toast-notification/dist/theme-bootstrap.css'
import 'vue3-perfect-scrollbar/style.css'
import { fetchGlobalSettings } from './api'
// 创建Vue实例
const app = createApp(App)
async function initializeApp() {
try {
// 是否为PWA
const appMode = await isPWA()
app.provide('appMode', appMode)
// 全局设置
const globalSettings = await fetchGlobalSettings()
// 使用 provide 传递全局设置
app.provide('globalSettings', globalSettings)
} catch (error) {
console.error('Failed to initialize app', error)

View File

@@ -8,10 +8,7 @@ import DashboardElement from '@/components/misc/DashboardElement.vue'
import { useDisplay } from 'vuetify'
// APP
const display = useDisplay()
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 从Vuex Store中获取superuser信息
const superUser = store.state.auth.superUser

View File

@@ -7,10 +7,7 @@ import TorrentRowListView from '@/views/discover/TorrentRowListView.vue'
import { useDisplay } from 'vuetify'
// APP
const display = useDisplay()
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 路由参数
const route = useRoute()

View File

@@ -8,9 +8,7 @@ import { useDisplay } from 'vuetify'
const display = useDisplay()
// APP
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 定义输入参数
const props = defineProps({
@@ -38,7 +36,7 @@ const filterForm = reactive({
// 列表样式
const listStyle = computed(() => {
return appMode.value
return appMode
? 'height: calc(100vh - 7.5rem - env(safe-area-inset-bottom) - 3.5rem)'
: 'height: calc(100vh - 6.5rem - env(safe-area-inset-bottom)'
})

View File

@@ -16,9 +16,7 @@ const route = useRoute()
const display = useDisplay()
// APP
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 当前标签
const activeTab = ref(route.query.tab)

View File

@@ -10,13 +10,8 @@ import router from '@/router'
import { useDisplay } from 'vuetify'
import { storageDict } from '@/api/constants'
// 显示器宽度
const display = useDisplay()
// APP
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 提示框
const $toast = useToast()
@@ -126,7 +121,7 @@ const TransferDict: { [key: string]: string } = {
}
const tableStyle = computed(() => {
return appMode.value
return appMode
? 'height: calc(100vh - 15.5rem - env(safe-area-inset-bottom) - 3.5rem)'
: 'height: calc(100vh - 14.5rem - env(safe-area-inset-bottom)'
})

View File

@@ -7,13 +7,8 @@ import NoDataFound from '@/components/NoDataFound.vue'
import SiteAddEditDialog from '@/components/dialog/SiteAddEditDialog.vue'
import { useDisplay } from 'vuetify'
// 显示器宽度
const display = useDisplay()
// APP
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 站点列表
const siteList = ref<Site[]>([])

View File

@@ -9,13 +9,8 @@ import SubscribeHistoryDialog from '@/components/dialog/SubscribeHistoryDialog.v
import store from '@/store'
import { useDisplay } from 'vuetify'
// 显示器宽度
const display = useDisplay()
// APP
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 输入参数
const props = defineProps({

View File

@@ -7,10 +7,7 @@ import UserCard from '@/components/cards/UserCard.vue'
import UserAddEditDialog from '@/components/dialog/UserAddEditDialog.vue'
// APP
const display = useDisplay()
const appMode = computed(() => {
return localStorage.getItem('MP_APPMODE') != '0' && display.mdAndDown.value
})
const appMode = inject('appMode')
// 是否刷新过
const isRefreshed = ref(false)
@@ -58,7 +55,7 @@ onActivated(() => {
<template>
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
<div v-if="allUsers.length > 0" class="grid gap-3 grid-user-card items-start">
<div v-if="allUsers.length > 0" class="grid gap-3 grid-user-card">
<UserCard v-for="user in allUsers" :user="user" :users="allUsers" @remove="loadAllUsers" @save="loadAllUsers" />
</div>