mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-30 21:00:43 +08:00
Refactor navigator utility functions and add isPWA check
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
// 用户重新完成时
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)'
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)'
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)'
|
||||
})
|
||||
|
||||
@@ -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[]>([])
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user