Compare commits

...

9 commits

Author SHA1 Message Date
Thomas Ricouard e21ec0bd1f Add expanded sidebar layout 2024-05-08 11:51:28 +02:00
Thomas Ricouard 9c42a3d7cc Add copy button for alt text 2024-05-08 11:03:25 +02:00
Thomas Ricouard 54a16b2c9a Fix unboost icon 2024-05-08 11:00:40 +02:00
Thomas Ricouard a6f3068728 Add accounts list placeholder 2024-05-08 10:59:31 +02:00
Thomas Ricouard f04258ec04 Revert "Delete unused functions in TimelineDatasource.swift (#2037)"
This reverts commit e9a2d3e151.
2024-05-08 10:50:22 +02:00
Cthulhux 8468e51c17
de: Update Localizable.xcstrings (#2057)
(Not entirely sure whether to translate "TimelineFilter" et al.)
2024-05-08 10:39:09 +02:00
Noah Martin e9a2d3e151
Delete unused functions in TimelineDatasource.swift (#2037) 2024-05-08 10:38:36 +02:00
Igor Camilo 1f56fa1b9b
Add tooltip to sidebar buttons. (#2040) 2024-05-08 10:38:27 +02:00
Jerry Zhang ccad00a094
Update Simplified Chinese localization (#2052)
* Update Simplified Chinese localization

* Fix

---------

Co-authored-by: Thomas Ricouard <ricouard77@gmail.com>
2024-05-08 10:32:26 +02:00
9 changed files with 714 additions and 186 deletions

View file

@ -35,15 +35,23 @@ struct SideBarView<Content: View>: View {
} }
private func makeIconForTab(tab: Tab) -> some View { private func makeIconForTab(tab: Tab) -> some View {
ZStack(alignment: .topTrailing) { HStack {
SideBarIcon(systemIconName: tab.iconName, ZStack(alignment: .topTrailing) {
isSelected: tab == selectedTab) SideBarIcon(systemIconName: tab.iconName,
let badge = badgeFor(tab: tab) isSelected: tab == selectedTab)
if badge > 0 { let badge = badgeFor(tab: tab)
makeBadgeView(count: badge) if badge > 0 {
makeBadgeView(count: badge)
}
}
if userPreferences.isSidebarExpanded {
Text(tab.title)
.font(.headline)
.foregroundColor(tab == selectedTab ? theme.tintColor : theme.labelColor)
.frame(maxWidth: .infinity, alignment: .leading)
} }
} }
.frame(width: .sidebarWidth - 24, height: 50) .frame(width: (userPreferences.isSidebarExpanded ? .sidebarWidthExpanded : .sidebarWidth) - 24, height: 50)
.background(tab == selectedTab ? theme.secondaryBackgroundColor : .clear, .background(tab == selectedTab ? theme.secondaryBackgroundColor : .clear,
in: RoundedRectangle(cornerRadius: 8)) in: RoundedRectangle(cornerRadius: 8))
} }
@ -75,6 +83,7 @@ struct SideBarView<Content: View>: View {
.offset(x: 2, y: -2) .offset(x: 2, y: -2)
} }
.buttonStyle(.borderedProminent) .buttonStyle(.borderedProminent)
.help(Tab.post.title)
} }
private func makeAccountButton(account: AppAccount, showBadge: Bool) -> some View { private func makeAccountButton(account: AppAccount, showBadge: Bool) -> some View {
@ -91,8 +100,17 @@ struct SideBarView<Content: View>: View {
} }
} label: { } label: {
ZStack(alignment: .topTrailing) { ZStack(alignment: .topTrailing) {
AppAccountView(viewModel: .init(appAccount: account, isCompact: true), if userPreferences.isSidebarExpanded {
isParentPresented: .constant(false)) AppAccountView(viewModel: .init(appAccount: account,
isCompact: false,
isInSettings: false),
isParentPresented: .constant(false))
} else {
AppAccountView(viewModel: .init(appAccount: account,
isCompact: true,
isInSettings: false),
isParentPresented: .constant(false))
}
if showBadge, if showBadge,
let token = account.oauthToken, let token = account.oauthToken,
let notificationsCount = userPreferences.notificationsCount[token], let notificationsCount = userPreferences.notificationsCount[token],
@ -101,13 +119,23 @@ struct SideBarView<Content: View>: View {
makeBadgeView(count: notificationsCount) makeBadgeView(count: notificationsCount)
} }
} }
.padding(.leading, userPreferences.isSidebarExpanded ? 16 : 0)
} }
.frame(width: .sidebarWidth, height: 50) .help(accountButtonTitle(accountName: account.accountName))
.frame(width: userPreferences.isSidebarExpanded ? .sidebarWidthExpanded : .sidebarWidth, height: 50)
.padding(.vertical, 8) .padding(.vertical, 8)
.background(selectedTab == .profile && account.id == appAccounts.currentAccount.id ? .background(selectedTab == .profile && account.id == appAccounts.currentAccount.id ?
theme.secondaryBackgroundColor : .clear) theme.secondaryBackgroundColor : .clear)
} }
private func accountButtonTitle(accountName: String?) -> LocalizedStringKey {
if let accountName {
"tab.profile-account-\(accountName)"
} else {
Tab.profile.title
}
}
private var tabsView: some View { private var tabsView: some View {
ForEach(tabs) { tab in ForEach(tabs) { tab in
if tab != .profile && sidebarTabs.isEnabled(tab) { if tab != .profile && sidebarTabs.isEnabled(tab) {
@ -132,6 +160,7 @@ struct SideBarView<Content: View>: View {
} label: { } label: {
makeIconForTab(tab: tab) makeIconForTab(tab: tab)
} }
.help(tab.title)
} }
} }
} }
@ -155,15 +184,22 @@ struct SideBarView<Content: View>: View {
} }
} }
} }
.frame(width: .sidebarWidth) .frame(width: userPreferences.isSidebarExpanded ? .sidebarWidthExpanded : .sidebarWidth)
.scrollContentBackground(.hidden) .scrollContentBackground(.hidden)
.background(.thinMaterial) .background(.thinMaterial)
.safeAreaInset(edge: .bottom, content: { .safeAreaInset(edge: .bottom, content: {
HStack { HStack(spacing: 16) {
postButton postButton
.padding(.vertical, 24) .padding(.vertical, 24)
.padding(.leading, userPreferences.isSidebarExpanded ? 18 : 0)
if userPreferences.isSidebarExpanded {
Text("menu.new-post")
.font(.subheadline)
.foregroundColor(theme.labelColor)
.frame(maxWidth: .infinity, alignment: .leading)
}
} }
.frame(width: .sidebarWidth) .frame(width: userPreferences.isSidebarExpanded ? .sidebarWidthExpanded : .sidebarWidth)
.background(.thinMaterial) .background(.thinMaterial)
}) })
Divider().edgesIgnoringSafeArea(.all) Divider().edgesIgnoringSafeArea(.all)
@ -196,6 +232,7 @@ private struct SideBarIcon: View {
self.isHovered = isHovered self.isHovered = isHovered
} }
} }
.frame(width: 50, height: 40)
} }
} }

View file

@ -80,41 +80,47 @@ enum Tab: Int, Identifiable, Hashable, CaseIterable, Codable {
@ViewBuilder @ViewBuilder
var label: some View { var label: some View {
if self != .other {
Label(title, systemImage: iconName)
}
}
var title: LocalizedStringKey {
switch self { switch self {
case .timeline: case .timeline:
Label("tab.timeline", systemImage: iconName) "tab.timeline"
case .trending: case .trending:
Label("tab.trending", systemImage: iconName) "tab.trending"
case .local: case .local:
Label("tab.local", systemImage: iconName) "tab.local"
case .federated: case .federated:
Label("tab.federated", systemImage: iconName) "tab.federated"
case .notifications: case .notifications:
Label("tab.notifications", systemImage: iconName) "tab.notifications"
case .mentions: case .mentions:
Label("tab.mentions", systemImage: iconName) "tab.mentions"
case .explore: case .explore:
Label("tab.explore", systemImage: iconName) "tab.explore"
case .messages: case .messages:
Label("tab.messages", systemImage: iconName) "tab.messages"
case .settings: case .settings:
Label("tab.settings", systemImage: iconName) "tab.settings"
case .profile: case .profile:
Label("tab.profile", systemImage: iconName) "tab.profile"
case .bookmarks: case .bookmarks:
Label("accessibility.tabs.profile.picker.bookmarks", systemImage: iconName) "accessibility.tabs.profile.picker.bookmarks"
case .favorites: case .favorites:
Label("accessibility.tabs.profile.picker.favorites", systemImage: iconName) "accessibility.tabs.profile.picker.favorites"
case .post: case .post:
Label("menu.new-post", systemImage: iconName) "menu.new-post"
case .followedTags: case .followedTags:
Label("timeline.filter.tags", systemImage: iconName) "timeline.filter.tags"
case .lists: case .lists:
Label("timeline.filter.lists", systemImage: iconName) "timeline.filter.lists"
case .links: case .links:
Label("explore.section.trending.links", systemImage: iconName) "explore.section.trending.links"
case .other: case .other:
EmptyView() ""
} }
} }

View file

@ -14,6 +14,21 @@ struct ToolbarTab: ToolbarContent {
var body: some ToolbarContent { var body: some ToolbarContent {
if !isSecondaryColumn { if !isSecondaryColumn {
ToolbarItem(placement: .topBarLeading) {
if UIDevice.current.userInterfaceIdiom == .pad || UIDevice.current.userInterfaceIdiom == .mac {
Button {
withAnimation {
userPreferences.isSidebarExpanded.toggle()
}
} label: {
if userPreferences.isSidebarExpanded {
Image(systemName: "sidebar.squares.left")
} else {
Image(systemName: "sidebar.left")
}
}
}
}
statusEditorToolbarItem(routerPath: routerPath, statusEditorToolbarItem(routerPath: routerPath,
visibility: userPreferences.postVisibility) visibility: userPreferences.postVisibility)
if UIDevice.current.userInterfaceIdiom != .pad || if UIDevice.current.userInterfaceIdiom != .pad ||

File diff suppressed because it is too large Load diff

View file

@ -124,16 +124,23 @@ public struct AccountsListView: View {
} }
} }
Section { Section {
ForEach(accounts) { account in if accounts.isEmpty {
if let relationship = relationships.first(where: { $0.id == account.id }) { PlaceholderView(iconName: "person.icloud",
AccountsListRow(viewModel: .init(account: account, title: "No accounts found",
relationShip: relationship)) message: "This list of accounts is empty")
#if !os(visionOS) .listRowSeparator(.hidden)
.listRowBackground(theme.primaryBackgroundColor) } else {
#endif ForEach(accounts) { account in
if let relationship = relationships.first(where: { $0.id == account.id }) {
AccountsListRow(viewModel: .init(account: account,
relationShip: relationship))
}
} }
} }
} }
#if !os(visionOS)
.listRowBackground(theme.primaryBackgroundColor)
#endif
switch nextPageState { switch nextPageState {
case .hasNextPage: case .hasNextPage:

View file

@ -9,5 +9,6 @@ public extension CGFloat {
static let statusComponentSpacing: CGFloat = 6 static let statusComponentSpacing: CGFloat = 6
static let secondaryColumnWidth: CGFloat = 400 static let secondaryColumnWidth: CGFloat = 400
static let sidebarWidth: CGFloat = 90 static let sidebarWidth: CGFloat = 90
static let sidebarWidthExpanded: CGFloat = 220
static let pollBarHeight: CGFloat = 30 static let pollBarHeight: CGFloat = 30
} }

View file

@ -60,6 +60,8 @@ import SwiftUI
@AppStorage("show_reply_indentation") public var showReplyIndentation: Bool = true @AppStorage("show_reply_indentation") public var showReplyIndentation: Bool = true
@AppStorage("show_account_popover") public var showAccountPopover: Bool = true @AppStorage("show_account_popover") public var showAccountPopover: Bool = true
@AppStorage("sidebar_expanded") public var isSidebarExpanded: Bool = false
init() {} init() {}
} }
@ -326,6 +328,12 @@ import SwiftUI
storage.showAccountPopover = showAccountPopover storage.showAccountPopover = showAccountPopover
} }
} }
public var isSidebarExpanded: Bool {
didSet {
storage.isSidebarExpanded = isSidebarExpanded
}
}
public func getRealMaxIndent() -> UInt { public func getRealMaxIndent() -> UInt {
showReplyIndentation ? maxReplyIndentation : 0 showReplyIndentation ? maxReplyIndentation : 0
@ -501,6 +509,7 @@ import SwiftUI
showReplyIndentation = storage.showReplyIndentation showReplyIndentation = storage.showReplyIndentation
showAccountPopover = storage.showAccountPopover showAccountPopover = storage.showAccountPopover
muteVideo = storage.muteVideo muteVideo = storage.muteVideo
isSidebarExpanded = storage.isSidebarExpanded
} }
} }

View file

@ -31,7 +31,7 @@ struct StatusRowContextMenu: View {
} }
if statusDataController.isReblogged { if statusDataController.isReblogged {
return Label("status.action.unboost", image: "Rocket.fill") return Label("status.action.unboost", image: "Rocket.Fill")
} }
return Label("status.action.boost", image: "Rocket") return Label("status.action.boost", image: "Rocket")
} }

View file

@ -288,6 +288,7 @@ struct AltTextButton: View {
isPresented: $isDisplayingAlert isPresented: $isDisplayingAlert
) { ) {
Button("alert.button.ok", action: {}) Button("alert.button.ok", action: {})
Button("status.action.copy-text", action: { UIPasteboard.general.string = text })
} message: { } message: {
Text(text) Text(text)
} }