Merge branch 'main' into tip-system

This commit is contained in:
Thomas Ricouard 2024-07-20 19:14:54 +02:00
commit 6cb8686834
16 changed files with 572 additions and 107 deletions

View file

@ -1193,7 +1193,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1228,7 +1228,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesNotifications";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1267,7 +1267,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesAppWidgetsExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesAppWidgetsExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1303,7 +1303,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesAppWidgetsExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesAppWidgetsExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1336,7 +1336,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1370,7 +1370,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesShareExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1552,7 +1552,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp";
PRODUCT_NAME = "Ice Cubes"; PRODUCT_NAME = "Ice Cubes";
SDKROOT = auto; SDKROOT = auto;
@ -1608,7 +1608,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13.0; MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp";
PRODUCT_NAME = "Ice Cubes"; PRODUCT_NAME = "Ice Cubes";
SDKROOT = auto; SDKROOT = auto;
@ -1643,7 +1643,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -1678,7 +1678,7 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 1.10.45; MARKETING_VERSION = 1.10.46;
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos; SDKROOT = iphoneos;

View file

@ -37,7 +37,7 @@ struct DisplaySettingsView: View {
ZStack(alignment: .top) { ZStack(alignment: .top) {
Form { Form {
#if !os(visionOS) #if !os(visionOS)
StatusRowView(viewModel: previewStatusViewModel) StatusRowExternalView(viewModel: previewStatusViewModel)
.allowsHitTesting(false) .allowsHitTesting(false)
.opacity(0) .opacity(0)
.hidden() .hidden()
@ -85,7 +85,7 @@ struct DisplaySettingsView: View {
private var examplePost: some View { private var examplePost: some View {
VStack(spacing: 0) { VStack(spacing: 0) {
StatusRowView(viewModel: previewStatusViewModel) StatusRowExternalView(viewModel: previewStatusViewModel)
.allowsHitTesting(false) .allowsHitTesting(false)
.padding(.layoutPadding) .padding(.layoutPadding)
.background(theme.primaryBackgroundColor) .background(theme.primaryBackgroundColor)
@ -237,6 +237,7 @@ struct DisplaySettingsView: View {
} }
} }
Toggle("settings.display.show-account-popover", isOn: $userPreferences.showAccountPopover) Toggle("settings.display.show-account-popover", isOn: $userPreferences.showAccountPopover)
Toggle("Show Content Gradient", isOn: $theme.showContentGradient)
} }
#if !os(visionOS) #if !os(visionOS)
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)

View file

@ -37,6 +37,11 @@ struct AddRemoteTimelineView: View {
.foregroundColor(.green) .foregroundColor(.green)
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
} }
if !instanceName.isEmpty && instance == nil {
Label("timeline.\(instanceName)-not-valid", systemImage: "xmark.seal.fill")
.foregroundColor(.red)
.listRowBackground(theme.primaryBackgroundColor)
}
Button { Button {
guard instance != nil else { return } guard instance != nil else { return }
context.insert(LocalTimeline(instance: instanceName)) context.insert(LocalTimeline(instance: instanceName))
@ -45,6 +50,7 @@ struct AddRemoteTimelineView: View {
Text("timeline.add.action.add") Text("timeline.add.action.add")
} }
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
.disabled(instance == nil)
instancesListView instancesListView
} }

File diff suppressed because it is too large Load diff

View file

@ -239,7 +239,7 @@ public struct AccountDetailView: View {
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
#endif #endif
ForEach(viewModel.pinned) { status in ForEach(viewModel.pinned) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowExternalView(viewModel: .init(status: status, client: client, routerPath: routerPath))
} }
Rectangle() Rectangle()
#if os(visionOS) #if os(visionOS)

View file

@ -13,6 +13,7 @@ public final class Theme {
case displayFullUsernameTimeline case displayFullUsernameTimeline
case lineSpacing case lineSpacing
case statusActionSecondary case statusActionSecondary
case contentGradient
} }
@AppStorage("is_previously_set") public var isThemePreviouslySet: Bool = false @AppStorage("is_previously_set") public var isThemePreviouslySet: Bool = false
@ -30,6 +31,7 @@ public final class Theme {
@AppStorage(ThemeKey.displayFullUsernameTimeline.rawValue) public var displayFullUsername: Bool = false @AppStorage(ThemeKey.displayFullUsernameTimeline.rawValue) public var displayFullUsername: Bool = false
@AppStorage(ThemeKey.lineSpacing.rawValue) public var lineSpacing: Double = 1.2 @AppStorage(ThemeKey.lineSpacing.rawValue) public var lineSpacing: Double = 1.2
@AppStorage(ThemeKey.statusActionSecondary.rawValue) public var statusActionSecondary: StatusActionSecondary = .share @AppStorage(ThemeKey.statusActionSecondary.rawValue) public var statusActionSecondary: StatusActionSecondary = .share
@AppStorage(ThemeKey.contentGradient.rawValue) public var showContentGradient: Bool = true
@AppStorage("font_size_scale") public var fontSizeScale: Double = 1 @AppStorage("font_size_scale") public var fontSizeScale: Double = 1
@AppStorage("chosen_font") public var chosenFontData: Data? @AppStorage("chosen_font") public var chosenFontData: Data?
@ -282,6 +284,12 @@ public final class Theme {
themeStorage.chosenFontData = chosenFontData themeStorage.chosenFontData = chosenFontData
} }
} }
public var showContentGradient: Bool {
didSet {
themeStorage.showContentGradient = showContentGradient
}
}
public var selectedSet: ColorSetName = .iceCubeDark public var selectedSet: ColorSetName = .iceCubeDark
@ -301,6 +309,7 @@ public final class Theme {
fontSizeScale = 1 fontSizeScale = 1
chosenFontData = nil chosenFontData = nil
statusActionSecondary = .share statusActionSecondary = .share
showContentGradient = true
} }
private init() { private init() {
@ -322,6 +331,7 @@ public final class Theme {
fontSizeScale = themeStorage.fontSizeScale fontSizeScale = themeStorage.fontSizeScale
chosenFontData = themeStorage.chosenFontData chosenFontData = themeStorage.chosenFontData
statusActionSecondary = themeStorage.statusActionSecondary statusActionSecondary = themeStorage.statusActionSecondary
showContentGradient = themeStorage.showContentGradient
selectedSet = storedSet selectedSet = storedSet
computeContrastingTintColor() computeContrastingTintColor()

View file

@ -155,7 +155,7 @@ public struct ExploreView: View {
private var loadingView: some View { private var loadingView: some View {
ForEach(Status.placeholders()) { status in ForEach(Status.placeholders()) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowExternalView(viewModel: .init(status: status, client: client, routerPath: routerPath))
.padding(.vertical, 8) .padding(.vertical, 8)
.redacted(reason: .placeholder) .redacted(reason: .placeholder)
.allowsHitTesting(false) .allowsHitTesting(false)
@ -201,7 +201,7 @@ public struct ExploreView: View {
if !results.statuses.isEmpty, viewModel.searchScope == .all || viewModel.searchScope == .posts { if !results.statuses.isEmpty, viewModel.searchScope == .all || viewModel.searchScope == .posts {
Section("explore.section.posts") { Section("explore.section.posts") {
ForEach(results.statuses) { status in ForEach(results.statuses) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowExternalView(viewModel: .init(status: status, client: client, routerPath: routerPath))
#if !os(visionOS) #if !os(visionOS)
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
#else #else
@ -279,7 +279,7 @@ public struct ExploreView: View {
ForEach(viewModel.trendingStatuses ForEach(viewModel.trendingStatuses
.prefix(upTo: viewModel.trendingStatuses.count > 3 ? 3 : viewModel.trendingStatuses.count)) .prefix(upTo: viewModel.trendingStatuses.count > 3 ? 3 : viewModel.trendingStatuses.count))
{ status in { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowExternalView(viewModel: .init(status: status, client: client, routerPath: routerPath))
#if !os(visionOS) #if !os(visionOS)
.listRowBackground(theme.primaryBackgroundColor) .listRowBackground(theme.primaryBackgroundColor)
#else #else

View file

@ -156,17 +156,17 @@ struct NotificationRowView: View {
if let status = notification.status { if let status = notification.status {
HStack { HStack {
if type == .mention { if type == .mention {
StatusRowView(viewModel: .init(status: status, StatusRowExternalView(viewModel: .init(status: status,
client: client, client: client,
routerPath: routerPath, routerPath: routerPath,
showActions: true)) showActions: true))
.environment(\.isMediaCompact, false) .environment(\.isMediaCompact, false)
} else { } else {
StatusRowView(viewModel: .init(status: status, StatusRowExternalView(viewModel: .init(status: status,
client: client, client: client,
routerPath: routerPath, routerPath: routerPath,
showActions: false, showActions: false,
textDisabled: true)) textDisabled: true))
.lineLimit(4) .lineLimit(4)
.environment(\.isMediaCompact, true) .environment(\.isMediaCompact, true)
} }

View file

@ -155,7 +155,7 @@ public struct StatusDetailView: View {
private var loadingDetailView: some View { private var loadingDetailView: some View {
ForEach(Status.placeholders()) { status in ForEach(Status.placeholders()) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath), context: .timeline)
.redacted(reason: .placeholder) .redacted(reason: .placeholder)
.allowsHitTesting(false) .allowsHitTesting(false)
} }

View file

@ -129,7 +129,8 @@ extension StatusEditor {
StatusRowView(viewModel: .init(status: status, StatusRowView(viewModel: .init(status: status,
client: client, client: client,
routerPath: RouterPath(), routerPath: RouterPath(),
showActions: false)) showActions: false),
context: .timeline)
.accessibilityLabel(status.content.asRawText) .accessibilityLabel(status.content.asRawText)
.environment(RouterPath()) .environment(RouterPath())
.allowsHitTesting(false) .allowsHitTesting(false)

View file

@ -26,7 +26,8 @@ public struct StatusEmbeddedView: View {
StatusRowView(viewModel: .init(status: status, StatusRowView(viewModel: .init(status: status,
client: client, client: client,
routerPath: routerPath, routerPath: routerPath,
showActions: false)) showActions: false),
context: .timeline)
.accessibilityLabel(status.content.asRawText) .accessibilityLabel(status.content.asRawText)
.environment(\.isCompact, true) .environment(\.isCompact, true)
.environment(\.isMediaCompact, true) .environment(\.isMediaCompact, true)

View file

@ -29,7 +29,8 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
switch fetcher.statusesState { switch fetcher.statusesState {
case .loading: case .loading:
ForEach(Status.placeholders()) { status in ForEach(Status.placeholders()) { status in
StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath)) StatusRowView(viewModel: .init(status: status, client: client, routerPath: routerPath),
context: .timeline)
.redacted(reason: .placeholder) .redacted(reason: .placeholder)
.allowsHitTesting(false) .allowsHitTesting(false)
} }
@ -44,11 +45,12 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
case let .display(statuses, nextPageState): case let .display(statuses, nextPageState):
ForEach(statuses, id: \.id) { status in ForEach(statuses) { status in
StatusRowView(viewModel: StatusRowViewModel(status: status, StatusRowView(viewModel: StatusRowViewModel(status: status,
client: client, client: client,
routerPath: routerPath, routerPath: routerPath,
isRemote: isRemote)) isRemote: isRemote),
context: .timeline)
.onAppear { .onAppear {
fetcher.statusDidAppear(status: status) fetcher.statusDidAppear(status: status)
} }

View file

@ -0,0 +1,15 @@
import SwiftUI
public struct StatusRowExternalView: View {
@State private var viewModel: StatusRowViewModel
private let context: StatusRowView.Context
public init(viewModel: StatusRowViewModel, context: StatusRowView.Context = .timeline) {
_viewModel = .init(initialValue: viewModel)
self.context = context
}
public var body: some View {
StatusRowView(viewModel: viewModel, context: context)
}
}

View file

@ -22,17 +22,13 @@ public struct StatusRowView: View {
@Environment(Theme.self) private var theme @Environment(Theme.self) private var theme
@Environment(Client.self) private var client @Environment(Client.self) private var client
@State private var viewModel: StatusRowViewModel
@State private var showSelectableText: Bool = false @State private var showSelectableText: Bool = false
@State private var isBlockConfirmationPresented = false @State private var isBlockConfirmationPresented = false
public enum Context { case timeline, detail } public enum Context { case timeline, detail }
private let context: Context
@State public var viewModel: StatusRowViewModel
public init(viewModel: StatusRowViewModel, context: Context = .timeline) { public let context: Context
_viewModel = .init(initialValue: viewModel)
self.context = context
}
var contextMenu: some View { var contextMenu: some View {
StatusRowContextMenu(viewModel: viewModel, StatusRowContextMenu(viewModel: viewModel,

View file

@ -108,7 +108,7 @@ import SwiftUI
@ViewBuilder @ViewBuilder
func makeBackgroundColor(isHomeTimeline: Bool) -> some View { func makeBackgroundColor(isHomeTimeline: Bool) -> some View {
if isHomeTimeline { if isHomeTimeline, theme.showContentGradient {
homeBackgroundColor homeBackgroundColor
} else { } else {
backgroundColor backgroundColor
@ -149,10 +149,10 @@ import SwiftUI
func makeDecorativeGradient(startColor: Color, endColor: Color) -> some View { func makeDecorativeGradient(startColor: Color, endColor: Color) -> some View {
LinearGradient(stops: [ LinearGradient(stops: [
.init(color: startColor.opacity(0.3), location: 0.03), .init(color: startColor.opacity(0.2), location: 0.03),
.init(color: startColor.opacity(0.2), location: 0.06), .init(color: startColor.opacity(0.1), location: 0.06),
.init(color: startColor.opacity(0.1), location: 0.09), .init(color: startColor.opacity(0.05), location: 0.09),
.init(color: startColor.opacity(0.05), location: 0.15), .init(color: startColor.opacity(0.02), location: 0.15),
.init(color: endColor, location: 0.25), .init(color: endColor, location: 0.25),
], ],
startPoint: .topLeading, startPoint: .topLeading,

View file

@ -104,7 +104,7 @@ struct StatusRowContextMenu: View {
Button { Button {
let view = HStack { let view = HStack {
StatusRowView(viewModel: viewModel) StatusRowView(viewModel: viewModel, context: .timeline)
.padding(16) .padding(16)
} }
.environment(\.isInCaptureMode, true) .environment(\.isInCaptureMode, true)