docs(readme): 📝 update platform support information for macOS and iOS

Add Mac26 support confirmation for macOS
Clarify iOS26 real device support and Intel chip simulator limitation
Update both English and Chinese documentation files
This commit is contained in:
Dawn
2025-11-20 19:26:02 +08:00
parent 58812f90ce
commit b340f36f77
10 changed files with 72 additions and 89 deletions

View File

@@ -95,9 +95,9 @@
| Platform | Supported Versions |
|----------|-------------------|
| Windows | Windows 10, Windows 11 |
| macOS | macOS 10.5+ |
| macOS | macOS 10.5+ Mac26 has supported |
| Linux | Ubuntu 22.0+ |
| iOS | iOS 9.0+ ⚠️(ios26 compatible) |
| iOS | iOS 9.0+ (iOS26 Real machine is supported. Tauri does not support Intel chips running on ios26 emulators) |
| Android | Android 12+ (SDK30+) |
| Web | ⚠Not currently supported (custom removal required) |

View File

@@ -94,9 +94,9 @@
| 平台 | 支持版本 |
| ------- | ------------------------------------ |
| Windows | Windows 10, Windows 11 |
| macOS | macOS 10.5+ |
| macOS | macOS 10.5+ Mac26已支持 |
| Linux | Ubuntu 22.0+ |
| iOS | iOS 9.0+ ios26后续兼容 |
| iOS | iOS 9.0+ (iOS26 真机已支持, Tauri不支持Intel芯片在ios26模拟器上运行) |
| Android | Android 12+ (SDK30+) |
| Web | ⚠️暂不支持(需要自定义移除对桌面功能) |

View File

@@ -96,9 +96,9 @@
| Platform | Supported Versions |
|----------|-------------------|
| Windows | Windows 10, Windows 11 |
| macOS | macOS 10.5+ |
| macOS | macOS 10.5+ Mac26 has supported |
| Linux | Ubuntu 22.0+ |
| iOS | iOS 9.0+ ⚠️(ios26 compatible) |
| iOS | iOS 9.0+ (iOS26 Real machine is supported. Tauri does not support Intel chips running on ios26 emulators) |
| Android | Android 12+ (SDK30+) |
| Web | ⚠Not currently supported (custom removal required) |

View File

@@ -95,9 +95,9 @@
| 平台 | 支持版本 |
| ------- | ------------------------------------ |
| Windows | Windows 10, Windows 11 |
| macOS | macOS 10.5+ |
| macOS | macOS 10.5+ Mac26已支持 |
| Linux | Ubuntu 22.0+ |
| iOS | iOS 9.0+ ios26后续兼容 |
| iOS | iOS 9.0+ (iOS26 真机已支持, Tauri不支持Intel芯片在ios26模拟器上运行) |
| Android | Android 12+ (SDK30+) |
| Web | ⚠️暂不支持(需要自定义移除对桌面功能) |

View File

@@ -544,9 +544,6 @@ const requestNetworkPermissionForIOS = async () => {
}
onMounted(() => {
// 初始化朋友圈通知存储
feedNotificationStore.initialize()
// iOS应用启动时预请求网络权限必须在最开始执行
if (isIOS()) {
requestNetworkPermissionForIOS()

View File

@@ -10,7 +10,7 @@
<h3 class="text-16px font-600">朋友圈通知</h3>
<div class="flex items-center gap-8px">
<n-button
v-if="notificationStore.notificationStats.unreadCount > 0"
v-if="feednotificationStore.notificationStats.unreadCount > 0"
text
type="primary"
size="small"
@@ -24,13 +24,13 @@
<!-- 通知列表 -->
<div class="flex-1 overflow-y-auto">
<div
v-if="notificationStore.notifications.length === 0"
v-if="feednotificationStore.notifications.length === 0"
class="flex items-center justify-center h-full text-#999">
暂无通知
</div>
<div
v-for="notification in notificationStore.notifications"
v-for="notification in feednotificationStore.notifications"
:key="notification.id"
class="border-b border-#f0f0f0 p-12px hover:bg-#f9f9f9 cursor-pointer transition-colors"
@click="handleNotificationClick(notification)">
@@ -73,7 +73,7 @@
</div>
<!-- 底部操作 -->
<div v-if="notificationStore.notifications.length > 0" class="border-t border-#e5e5e5 p-12px flex gap-8px">
<div v-if="feednotificationStore.notifications.length > 0" class="border-t border-#e5e5e5 p-12px flex gap-8px">
<n-button type="error" text block size="small" @click="clearAllNotifications">清空所有通知</n-button>
</div>
</div>
@@ -122,14 +122,14 @@
import { useFeedNotificationStore } from '@/stores/feedNotification'
import { AvatarUtils } from '@/utils/AvatarUtils'
const notificationStore = useFeedNotificationStore()
const feednotificationStore = useFeedNotificationStore()
const showPopup = ref(false)
const showCommentModal = ref(false)
const selectedNotification = ref<any>(null)
// 监听通知列表变化
watch(
() => notificationStore.notifications.length,
() => feednotificationStore.notifications.length,
(newLength) => {
console.log('📢 通知列表变化,当前通知数:', newLength)
}
@@ -139,8 +139,8 @@ watch(
* 打开弹窗
*/
const openPopup = () => {
console.log('🔔 打开通知弹窗,当前通知数:', notificationStore.notifications.length)
console.log('🔔 通知列表:', notificationStore.notifications)
console.log('🔔 打开通知弹窗,当前通知数:', feednotificationStore.notifications.length)
console.log('🔔 通知列表:', feednotificationStore.notifications)
showPopup.value = true
}
@@ -155,7 +155,7 @@ const closePopup = () => {
* 处理通知点击
*/
const handleNotificationClick = (notification: any) => {
notificationStore.markAsRead(notification.id)
feednotificationStore.markAsRead(notification.id)
selectedNotification.value = notification
showCommentModal.value = true
}
@@ -164,14 +164,14 @@ const handleNotificationClick = (notification: any) => {
* 标记所有为已读
*/
const markAllAsRead = () => {
notificationStore.markAllAsRead()
feednotificationStore.markAllAsRead()
}
/**
* 删除通知
*/
const deleteNotification = (notificationId: string) => {
notificationStore.deleteNotification(notificationId)
feednotificationStore.deleteNotification(notificationId)
}
/**
@@ -179,7 +179,7 @@ const deleteNotification = (notificationId: string) => {
*/
const clearAllNotifications = () => {
if (confirm('确定要清空所有通知吗?')) {
notificationStore.clearAllNotifications()
feednotificationStore.clearAllNotifications()
}
}

View File

@@ -195,7 +195,9 @@ export enum StoresEnum {
/** 文件管理 */
FILE = 'file',
/** 缩略图缓存 */
THUMBNAIL_CACHE = 'thumbnailCache'
THUMBNAIL_CACHE = 'thumbnailCache',
/** 初始化同步状态 */
INITIAL_SYNC = 'initialSync'
}
/**

View File

@@ -41,6 +41,7 @@ import { useChatStore } from '@/stores/chat'
import { useFileStore } from '@/stores/file'
import { useUserStore } from '@/stores/user'
import { useSettingStore } from '@/stores/setting.ts'
import { useInitialSyncStore } from '@/stores/initialSync.ts'
import { invokeSilently } from '@/utils/TauriInvokeHandler'
import { useRoute } from 'vue-router'
import { audioManager } from '@/utils/AudioManager'
@@ -50,48 +51,42 @@ const userStore = useUserStore()
const chatStore = useChatStore()
const fileStore = useFileStore()
const settingStore = useSettingStore()
// 负责记录哪些账号已经完成过首次同步的全局 store避免多账号串数据
const initialSyncStore = useInitialSyncStore()
const userUid = computed(() => userStore.userInfo?.uid ?? '')
const hasCachedSessions = computed(() => chatStore.sessionList.length > 0)
const appWindow = WebviewWindow.getCurrent()
const loadingPercentage = ref(10)
const loadingText = ref('正在加载应用...')
const { resetLoginState, logout, init } = useLogin()
const INITIAL_SYNC_FLAG_PREFIX = 'hula_initial_sync_'
const initialSyncStorageKey = computed(() => (userUid.value ? `${INITIAL_SYNC_FLAG_PREFIX}${userUid.value}` : ''))
// 是否需要阻塞首屏并做初始化同步
const requiresInitialSync = ref(true)
const shouldBlockInitialRender = computed(() => requiresInitialSync.value && !hasCachedSessions.value)
// 根据当前 uid 判断是否需要阻塞首屏并重新同步(依赖持久化的初始化完成名单)
const syncInitialSyncState = () => {
if (!initialSyncStorageKey.value || typeof window === 'undefined') {
if (!userUid.value || typeof window === 'undefined') {
requiresInitialSync.value = true
return
}
try {
requiresInitialSync.value = localStorage.getItem(initialSyncStorageKey.value) !== '1'
} catch (error) {
console.warn('[layout] 读取初始化标记失败:', error)
requiresInitialSync.value = true
}
requiresInitialSync.value = !initialSyncStore.isSynced(userUid.value)
}
watch(
() => initialSyncStorageKey.value,
() => userUid.value,
() => {
syncInitialSyncState()
},
{ immediate: true }
)
// 初始化同步成功后标记当前 uid后续启动直接走增量
const markInitialSyncCompleted = () => {
if (!initialSyncStorageKey.value || typeof window === 'undefined') {
if (!userUid.value || typeof window === 'undefined') {
requiresInitialSync.value = false
return
}
try {
localStorage.setItem(initialSyncStorageKey.value, '1')
} catch (error) {
console.warn('[layout] 写入初始化标记失败:', error)
}
initialSyncStore.markSynced(userUid.value)
requiresInitialSync.value = false
}

View File

@@ -18,6 +18,11 @@ export interface FeedNotificationItem {
isRead: boolean // 是否已读
}
interface NotificationStats {
unreadCount: number
totalCount: number
}
/**
* 朋友圈通知 Store
* 管理朋友圈的点赞和评论通知
@@ -27,7 +32,7 @@ export const useFeedNotificationStore = defineStore(StoresEnum.FEED_NOTIFICATION
const notifications = ref<FeedNotificationItem[]>([])
// 通知统计
const notificationStats = reactive({
const notificationStats = reactive<NotificationStats>({
unreadCount: 0, // 未读通知数
totalCount: 0 // 总通知数
})
@@ -52,9 +57,6 @@ export const useFeedNotificationStore = defineStore(StoresEnum.FEED_NOTIFICATION
if (!notification.isRead) {
notificationStats.unreadCount++
}
// 保存到本地存储
saveToLocalStorage()
}
}
@@ -66,7 +68,6 @@ export const useFeedNotificationStore = defineStore(StoresEnum.FEED_NOTIFICATION
if (notification && !notification.isRead) {
notification.isRead = true
notificationStats.unreadCount = Math.max(0, notificationStats.unreadCount - 1)
saveToLocalStorage()
}
}
@@ -78,7 +79,6 @@ export const useFeedNotificationStore = defineStore(StoresEnum.FEED_NOTIFICATION
n.isRead = true
})
notificationStats.unreadCount = 0
saveToLocalStorage()
}
/**
@@ -93,7 +93,6 @@ export const useFeedNotificationStore = defineStore(StoresEnum.FEED_NOTIFICATION
}
notifications.value.splice(index, 1)
notificationStats.totalCount = Math.max(0, notificationStats.totalCount - 1)
saveToLocalStorage()
}
}
@@ -104,46 +103,6 @@ export const useFeedNotificationStore = defineStore(StoresEnum.FEED_NOTIFICATION
notifications.value = []
notificationStats.unreadCount = 0
notificationStats.totalCount = 0
localStorage.removeItem('feedNotifications')
}
/**
* 保存到本地存储
*/
const saveToLocalStorage = () => {
try {
const data = {
notifications: notifications.value,
stats: notificationStats
}
localStorage.setItem('feedNotifications', JSON.stringify(data))
} catch (error) {
console.error('保存通知到本地存储失败:', error)
}
}
/**
* 从本地存储加载
*/
const loadFromLocalStorage = () => {
try {
const data = localStorage.getItem('feedNotifications')
if (data) {
const parsed = JSON.parse(data)
notifications.value = parsed.notifications || []
notificationStats.unreadCount = parsed.stats?.unreadCount || 0
notificationStats.totalCount = parsed.stats?.totalCount || 0
}
} catch (error) {
console.error('从本地存储加载通知失败:', error)
}
}
/**
* 初始化(应在应用启动时调用)
*/
const initialize = () => {
loadFromLocalStorage()
}
return {
@@ -153,7 +112,6 @@ export const useFeedNotificationStore = defineStore(StoresEnum.FEED_NOTIFICATION
markAsRead,
markAllAsRead,
deleteNotification,
clearAllNotifications,
initialize
clearAllNotifications
}
})

31
src/stores/initialSync.ts Normal file
View File

@@ -0,0 +1,31 @@
import { ref } from 'vue'
import { defineStore } from 'pinia'
import { StoresEnum } from '@/enums'
export const useInitialSyncStore = defineStore(StoresEnum.INITIAL_SYNC, () => {
const syncedUsers = ref<string[]>([])
/** 判断指定 uid 是否已经完成过初始化同步*/
const isSynced = (uid: string) => {
if (!uid) {
return false
}
return syncedUsers.value.includes(uid)
}
/** 标记指定 uid 已完成初始化同步 */
const markSynced = (uid: string) => {
if (!uid) {
return
}
if (!syncedUsers.value.includes(uid)) {
syncedUsers.value = [...syncedUsers.value, uid]
}
}
return {
syncedUsers,
isSynced,
markSynced
}
})