Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions iosApp/iosApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2025082901;
CURRENT_PROJECT_VERSION = 2025091001;
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
DEVELOPMENT_TEAM = 7LFDZ96332;
ENABLE_PREVIEWS = YES;
Expand All @@ -627,7 +627,7 @@
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 0.4.9;
MARKETING_VERSION = 0.5.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-lsqlite3",
Expand Down Expand Up @@ -657,7 +657,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2025082901;
CURRENT_PROJECT_VERSION = 2025091001;
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
DEVELOPMENT_TEAM = 7LFDZ96332;
ENABLE_PREVIEWS = YES;
Expand All @@ -675,7 +675,7 @@
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 15.0;
MARKETING_VERSION = 0.4.9;
MARKETING_VERSION = 0.5.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-lsqlite3",
Expand Down
7 changes: 4 additions & 3 deletions iosApp/iosApp/Data/ReleaseLogManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ struct ReleaseLogEntry {
}

@MainActor
class ReleaseLogManager: ObservableObject {
@Observable
class ReleaseLogManager {
static let shared = ReleaseLogManager()

@Published var releaseLogEntries: [ReleaseLogEntry] = []
@Published var isLoading = false
var releaseLogEntries: [ReleaseLogEntry] = []
var isLoading = false

private init() {
loadReleaseLog()
Expand Down
4 changes: 2 additions & 2 deletions iosApp/iosApp/FlareApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ struct FlareApp: SwiftUI.App {
#else
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
#endif
@StateObject private var router = FlareRouter.shared
@StateObject private var podcastManager = IOSPodcastManager.shared
@State private var router = FlareRouter.shared
@State private var podcastManager = IOSPodcastManager.shared
@State var theme = FlareTheme.shared
@State private var shouldShowVersionBanner: Bool = false

Expand Down
16 changes: 16 additions & 0 deletions iosApp/iosApp/ReleaseLog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
# Flare 0.5.0 Release Notes

## 🎉 新功能
- **Optimize code**: 将Swift UI低版本特性升级成iOS18+,性能更好
- **Timeline List**: 优化部分代码
- **Following/followers list**: 增加 关注/ 粉丝 列表

## 🎉 修复/调整
- **App Tabbar**: 调整App Tabbar 隐藏/显示逻辑
- **Release Notes**: 修复Release Notes 页面翻译显示重复问题
- **闪退**: 修复点赞等 调用KMP方法 闪退问题
- **多语言显示**: 调整X 的 部分显示内容

---


# Flare 0.4.9 Release Notes

## 🎉 新功能
Expand Down
9 changes: 5 additions & 4 deletions iosApp/iosApp/UI/Navigation/ComposeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import shared
import SwiftUI
import UIKit

class ComposeManager: ObservableObject {
@Observable
class ComposeManager {
static let shared = ComposeManager()

@Published var showCompose = false
@Published var composeAccountType: AccountType?
@Published var composeStatus: FlareComposeStatus?
var showCompose = false
var composeAccountType: AccountType?
var composeStatus: FlareComposeStatus?

private init() {}

Expand Down
13 changes: 8 additions & 5 deletions iosApp/iosApp/UI/Navigation/FlareRootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import SwiftUI

struct FlareRootView: View {
@State var menuState = FlareMenuState()
@StateObject private var router = FlareRouter.shared
@StateObject private var composeManager = ComposeManager.shared
@StateObject private var timelineState = TimelineExtState()
@State private var router = FlareRouter.shared
@State private var composeManager = ComposeManager.shared
@State private var timelineState = TimelineExtState()
@State private var presenter = ActiveAccountPresenter()
@Environment(\.appSettings) private var appSettings
@Environment(FlareTheme.self) private var theme
Expand Down Expand Up @@ -36,7 +36,7 @@ struct FlareRootView: View {
.applyTheme(theme)
.environment(menuState)
.environment(router)
.environmentObject(timelineState)
.environment(timelineState)
.sheet(isPresented: $router.isSheetPresented) {
if let destination = router.activeDestination {
FlareDestinationView(
Expand Down Expand Up @@ -67,7 +67,10 @@ struct FlareRootView: View {
secondaryButton: .cancel()
)
}
.sheet(isPresented: $composeManager.showCompose) {
.sheet(isPresented: Binding(
get: { composeManager.showCompose },
set: { composeManager.showCompose = $0 }
)) {
if let composeAccountType = composeManager.composeAccountType {
NavigationView {
ComposeScreen(
Expand Down
5 changes: 1 addition & 4 deletions iosApp/iosApp/UI/Navigation/FlareRouter.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import Combine
import os.log
import SafariServices
import shared
import SwiftUI
import UIKit

@Observable
class FlareRouter: ObservableObject {
class FlareRouter {
public static let shared = FlareRouter()

public var menuState: FlareMenuState

private var cancellables = Set<AnyCancellable>()

var activeDestination: FlareDestination?

var presentationType: FlarePresentationType = .push
Expand Down
15 changes: 9 additions & 6 deletions iosApp/iosApp/UI/Page/Compose/ErrorToast.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import SwiftUI

class ErrorToastManager: ObservableObject {
@Observable
class ErrorToastManager {
static let shared = ErrorToastManager()

@Published var isShowing = false
@Published var message = ""
var isShowing = false
var message = ""

private init() {}

Expand Down Expand Up @@ -70,17 +71,19 @@ extension View {
overlay(
ErrorToastOverlay()
)
.environmentObject(ErrorToastManager.shared)
}
}

struct ErrorToastOverlay: View {
@ObservedObject private var toastManager = ErrorToastManager.shared
private var toastManager = ErrorToastManager.shared

var body: some View {
ErrorToast(
message: toastManager.message,
isShowing: $toastManager.isShowing
isShowing: Binding(
get: { toastManager.isShowing },
set: { toastManager.isShowing = $0 }
)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,15 @@ struct TimelineStatusViewV2: View, Equatable {
static func == (lhs: TimelineStatusViewV2, rhs: TimelineStatusViewV2) -> Bool {
guard lhs.item.id == rhs.item.id else { return false }

return lhs.item.content.raw == rhs.item.content.raw &&
lhs.item.user?.key == rhs.item.user?.key &&
lhs.item.timestamp == rhs.item.timestamp &&

return lhs.item.id == rhs.item.id &&
lhs.item.likeCount == rhs.item.likeCount &&
lhs.item.isLiked == rhs.item.isLiked &&
lhs.item.retweetCount == rhs.item.retweetCount &&
lhs.item.isRetweeted == rhs.item.isRetweeted &&
lhs.item.replyCount == rhs.item.replyCount &&
lhs.item.bookmarkCount == rhs.item.bookmarkCount &&
lhs.item.isBookmarked == rhs.item.isBookmarked &&
lhs.item.sensitive == rhs.item.sensitive &&
lhs.item.images.count == rhs.item.images.count &&
lhs.isDetail == rhs.isDetail
lhs.item.sensitive == rhs.item.sensitive
}

@State private var state = TimelineItemState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import SwiftUI
struct TranslatableText: View {
let originalText: String
let forceTranslate: Bool
@StateObject private var transViewModel = TranslationViewModel()
@State private var transViewModel = TranslationViewModel()
private let languageDetector = LanguageDetector()
@Environment(\.appSettings) private var appSettings
@Environment(\.isInCaptureMode) private var isInCaptureMode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import Foundation
import SwiftUI

@MainActor
class TranslationViewModel: ObservableObject {
@Published var translatedText: String?
@Published var isTranslating = false
@Published var error: Error?
@Observable
class TranslationViewModel {
var translatedText: String?
var isTranslating = false
var error: Error?

private let translationService: TranslationService

Expand Down
32 changes: 11 additions & 21 deletions iosApp/iosApp/UI/Page/Home/Data/AppBarTabSettingStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,28 @@ extension Notification.Name {
static let listTitleDidUpdate = Notification.Name("listTitleDidUpdate")
}

class AppBarTabSettingStore: ObservableObject, TabStateProvider {
@Observable
class AppBarTabSettingStore: TabStateProvider {
static let shared = AppBarTabSettingStore(accountType: AccountTypeGuest())

@Published var primaryHomeItems: [FLTabItem] = [] // 主要标签(不可更改状态)Appbar 第一个Home 标签
@Published var secondaryItems: [FLTabItem] = [] // 所有次要标签
@Published var availableAppBarTabsItems: [FLTabItem] = [] // UserDefaults 存储的已启用标签
var primaryHomeItems: [FLTabItem] = [] // 主要标签(不可更改状态)Appbar 第一个Home 标签
var secondaryItems: [FLTabItem] = [] // 所有次要标签
var availableAppBarTabsItems: [FLTabItem] = [] // UserDefaults 存储的已启用标签

// 简化列表状态管理,只存储已pin的列表ID
@Published var pinnedListIds: [String] = [] // 收藏的列表ID
@Published var listTitles: [String: String] = [:] // 列表ID到标题的映射
@Published var listIconUrls: [String: String] = [:] // 列表ID到头像URL的映射
var pinnedListIds: [String] = [] // 收藏的列表ID
var listTitles: [String: String] = [:] // 列表ID到标题的映射
var listIconUrls: [String: String] = [:] // 列表ID到头像URL的映射

// 添加统一配置存储
private var appBarItems: [AppBarItemConfig] = []

// 添加同步锁,确保线程安全
private let storageLock = NSLock()

@Published var selectedAppBarTabKey: String = "" // 选中的 tab key
@Published var currentPresenter: TimelinePresenter?
@Published var currentUser: UiUserV2?
var selectedAppBarTabKey: String = "" // 选中的 tab key
var currentPresenter: TimelinePresenter?
var currentUser: UiUserV2?

private var presenter = ActiveAccountPresenter()
private let settingsManager = FLTabSettingsManager()
Expand Down Expand Up @@ -147,7 +148,6 @@ class AppBarTabSettingStore: ObservableObject, TabStateProvider {
listIconUrls = [:]
appBarItems = [] // 清空统一配置

objectWillChange.send()
FlareLog.debug("状态清除完成")
}

Expand Down Expand Up @@ -332,9 +332,6 @@ class AppBarTabSettingStore: ObservableObject, TabStateProvider {
} else if !availableAppBarTabsItems.isEmpty {
selectedAppBarTabKey = availableAppBarTabsItems[0].key
}

// 通知UI更新
objectWillChange.send()
}

// 从配置更新UI状态
Expand Down Expand Up @@ -563,7 +560,6 @@ class AppBarTabSettingStore: ObservableObject, TabStateProvider {
saveAppBarConfig()

// 发送变更通知
objectWillChange.send()
notificationService.postTabsDidUpdateNotification()

// 恢复选中状态
Expand Down Expand Up @@ -661,9 +657,6 @@ class AppBarTabSettingStore: ObservableObject, TabStateProvider {
newTitle: newTitle
)

// 通知UI更新
self.objectWillChange.send()

break
}
}
Expand Down Expand Up @@ -843,9 +836,6 @@ class AppBarTabSettingStore: ObservableObject, TabStateProvider {
}
}

// 通知UI更新
objectWillChange.send()

// 添加发送TabsDidUpdate通知,确保HomeTabController更新UI
notificationService.postTabsDidUpdateNotification()
FlareLog.debug("发送TabsDidUpdate通知,标签状态已更改: \(id)")
Expand Down
40 changes: 29 additions & 11 deletions iosApp/iosApp/UI/Page/Home/Model/TimelineExtState.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import SwiftUI

class TimelineExtState: ObservableObject {
@Published var scrollToTopTrigger = false
@Published var showFloatingButton = false
@Observable
class TimelineExtState {
var scrollToTopTrigger = false
var showFloatingButton = false

@Published var tabBarOffset: CGFloat = 0 // TabBar偏移量,0=显示,100=隐藏
var tabBarOffset: CGFloat = 0 // TabBar偏移量,0=显示,100=隐藏
private var lastScrollOffset: CGFloat = 0

func updateTabBarOffset(currentOffset: CGFloat, isHomeTab: Bool) {
Expand All @@ -15,24 +16,41 @@ class TimelineExtState: ObservableObject {
return
}

// 滚动到顶部时显示TabBar
if currentOffset <= 0 {
if tabBarOffset != 0 {
tabBarOffset = 0
lastScrollOffset = currentOffset
}
lastScrollOffset = currentOffset
return
}

let scrollDelta = currentOffset - lastScrollOffset

if scrollDelta > 30, tabBarOffset == 0 {
tabBarOffset = 100
}
// 向下滚动 隐藏TabBar
if scrollDelta > 0 {
guard tabBarOffset != 100 else {
lastScrollOffset = currentOffset
return
}

else if scrollDelta < -30, tabBarOffset != 0 {
tabBarOffset = 0
if scrollDelta > 30 {
tabBarOffset = 100
lastScrollOffset = currentOffset
}
}

lastScrollOffset = currentOffset
// 向上滚动 显示TabBar
else if scrollDelta < 0 {
guard tabBarOffset != 0 else {
lastScrollOffset = currentOffset
return
}

if scrollDelta < -10 {
tabBarOffset = 0
lastScrollOffset = currentOffset
}
}
}
}
Loading