mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Pinned events banner loading state (#3118)
This commit is contained in:
@@ -177,10 +177,10 @@ struct RoomScreenViewState: BindableState {
|
||||
// It's updated from the room info, so it's faster than using the timeline
|
||||
var pinnedEventIDs: Set<String> = []
|
||||
// This is used to control the banner
|
||||
var pinnedEventsState = PinnedEventsState()
|
||||
var pinnedEventsBannerState: PinnedEventsBannerState = .loading(numbersOfEvents: 0)
|
||||
|
||||
var shouldShowPinnedEventsBanner: Bool {
|
||||
isPinningEnabled && !pinnedEventsState.pinnedEventContents.isEmpty && lastScrollDirection != .top
|
||||
isPinningEnabled && !pinnedEventsBannerState.isEmpty && lastScrollDirection != .top
|
||||
}
|
||||
|
||||
var canJoinCall = false
|
||||
@@ -306,11 +306,12 @@ struct PinnedEventsState: Equatable {
|
||||
var pinnedEventContents: OrderedDictionary<String, AttributedString> = [:] {
|
||||
didSet {
|
||||
if selectedPinEventID == nil, !pinnedEventContents.keys.isEmpty {
|
||||
// The default selected event should always be the last one.
|
||||
selectedPinEventID = pinnedEventContents.keys.last
|
||||
} else if pinnedEventContents.isEmpty {
|
||||
selectedPinEventID = nil
|
||||
} else if let selectedPinEventID, !pinnedEventContents.keys.set.contains(selectedPinEventID) {
|
||||
self.selectedPinEventID = pinnedEventContents.firstNonNil { $0.key }
|
||||
self.selectedPinEventID = pinnedEventContents.keys.last
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -326,24 +327,15 @@ struct PinnedEventsState: Equatable {
|
||||
}
|
||||
|
||||
var selectedPinContent: AttributedString {
|
||||
guard let selectedPinEventID,
|
||||
var content = pinnedEventContents[selectedPinEventID] else {
|
||||
return AttributedString()
|
||||
var content = AttributedString(" ")
|
||||
if let selectedPinEventID,
|
||||
var pinnedEventContent = pinnedEventContents[selectedPinEventID] {
|
||||
content = pinnedEventContent
|
||||
}
|
||||
content.font = .compound.bodyMD
|
||||
return content
|
||||
}
|
||||
|
||||
var bannerIndicatorDescription: AttributedString {
|
||||
let index = selectedPinIndex + 1
|
||||
let boldPlaceholder = "{bold}"
|
||||
var finalString = AttributedString(L10n.screenRoomPinnedBannerIndicatorDescription(boldPlaceholder))
|
||||
var boldString = AttributedString(L10n.screenRoomPinnedBannerIndicator(index, pinnedEventContents.count))
|
||||
boldString.bold()
|
||||
finalString.replace(boldPlaceholder, with: boldString)
|
||||
return finalString
|
||||
}
|
||||
|
||||
mutating func nextPin() {
|
||||
guard !pinnedEventContents.isEmpty else {
|
||||
return
|
||||
@@ -353,3 +345,94 @@ struct PinnedEventsState: Equatable {
|
||||
selectedPinEventID = pinnedEventContents.keys[nextIndex]
|
||||
}
|
||||
}
|
||||
|
||||
enum PinnedEventsBannerState: Equatable {
|
||||
case loading(numbersOfEvents: Int)
|
||||
case loaded(state: PinnedEventsState)
|
||||
|
||||
var isEmpty: Bool {
|
||||
switch self {
|
||||
case .loaded(let state):
|
||||
return state.pinnedEventContents.isEmpty
|
||||
case .loading(let numberOfEvents):
|
||||
return numberOfEvents == 0
|
||||
}
|
||||
}
|
||||
|
||||
var isLoading: Bool {
|
||||
switch self {
|
||||
case .loading:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var selectedPinEventID: String? {
|
||||
switch self {
|
||||
case .loaded(let state):
|
||||
return state.selectedPinEventID
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var count: Int {
|
||||
switch self {
|
||||
case .loaded(let state):
|
||||
return state.pinnedEventContents.count
|
||||
case .loading(let numberOfEvents):
|
||||
return numberOfEvents
|
||||
}
|
||||
}
|
||||
|
||||
var selectedPinIndex: Int {
|
||||
switch self {
|
||||
case .loaded(let state):
|
||||
return state.selectedPinIndex
|
||||
case .loading(let numbersOfEvents):
|
||||
// We always want the index to be the last one when loading, since is the default one.
|
||||
return numbersOfEvents - 1
|
||||
}
|
||||
}
|
||||
|
||||
var displayedMessage: AttributedString {
|
||||
switch self {
|
||||
case .loading:
|
||||
return AttributedString(L10n.screenRoomPinnedBannerLoadingDescription)
|
||||
case .loaded(let state):
|
||||
return state.selectedPinContent
|
||||
}
|
||||
}
|
||||
|
||||
var bannerIndicatorDescription: AttributedString {
|
||||
let index = selectedPinIndex + 1
|
||||
let boldPlaceholder = "{bold}"
|
||||
var finalString = AttributedString(L10n.screenRoomPinnedBannerIndicatorDescription(boldPlaceholder))
|
||||
var boldString = AttributedString(L10n.screenRoomPinnedBannerIndicator(index, count))
|
||||
boldString.bold()
|
||||
finalString.replace(boldPlaceholder, with: boldString)
|
||||
return finalString
|
||||
}
|
||||
|
||||
mutating func nextPin() {
|
||||
switch self {
|
||||
case .loaded(var state):
|
||||
state.nextPin()
|
||||
self = .loaded(state: state)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
mutating func setPinnedEventContents(_ pinnedEventContents: OrderedDictionary<String, AttributedString>) {
|
||||
switch self {
|
||||
case .loading:
|
||||
// The default selected event should always be the last one.
|
||||
self = .loaded(state: .init(pinnedEventContents: pinnedEventContents, selectedPinEventID: pinnedEventContents.keys.last))
|
||||
case .loaded(var state):
|
||||
state.pinnedEventContents = pinnedEventContents
|
||||
self = .loaded(state: state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user