From e6de27efd88d651ef542355a8c73b18a71c300ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E4=B8=9A=E5=8D=87?= Date: Thu, 27 May 2021 23:04:55 +0800 Subject: [PATCH] Use List to resolve scrolling issue List to the rescue! --- Source/Hollow.xcodeproj/project.pbxproj | 25 ++- .../xcshareddata/swiftpm/Package.resolved | 9 + Source/Hollow/App/AppDelegate.swift | 2 - .../Hollow/View/Components/MyTextField.swift | 3 + Source/Hollow/View/Components/SearchBar.swift | 2 +- Source/Hollow/View/Components/Toast.swift | 7 +- .../Hierarchy/Account/SettingsSubViews.swift | 27 --- .../Hollow/Content/HollowImageView.swift | 6 +- .../Hollow/Content/HollowTextView.swift | 6 +- .../Hollow/Detail/HollowDetailSubViews.swift | 10 +- .../Hollow/Detail/HollowDetailView.swift | 172 ++++++++---------- .../Hollow/Input/HollowCommentInputView.swift | 1 - .../View/Hierarchy/Login/LoginSubViews.swift | 53 ++++-- .../View/Hierarchy/Login/WelcomeView.swift | 2 +- .../Hollow/View/Hierarchy/Main/MainView.swift | 11 +- .../View/Hierarchy/Main/TimelineView.swift | 31 ++-- Source/Hollow/en.lproj/Localizable.strings | 8 - .../Hollow/zh-Hans.lproj/Localizable.strings | 8 - .../Model/Extensions/DefaultsKeys.swift | 3 +- 19 files changed, 179 insertions(+), 207 deletions(-) diff --git a/Source/Hollow.xcodeproj/project.pbxproj b/Source/Hollow.xcodeproj/project.pbxproj index de97a072..31cdb08a 100644 --- a/Source/Hollow.xcodeproj/project.pbxproj +++ b/Source/Hollow.xcodeproj/project.pbxproj @@ -368,6 +368,7 @@ 0EDA263125D2465100B67292 /* LoadingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDA263025D2465100B67292 /* LoadingIndicator.swift */; }; 0EDEC0E52650E5A6003112BA /* View+makeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDEC0E42650E5A6003112BA /* View+makeButton.swift */; }; 0EE60EFD25FCCCD700D97E7A /* CheckmarkButtonImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EE60EFC25FCCCD700D97E7A /* CheckmarkButtonImage.swift */; }; + 0EEA957B265FE11400689E78 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 0EEA957A265FE11400689E78 /* Introspect */; }; 0EF10F6626330F29004D6538 /* HollowDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EF10F6526330F29004D6538 /* HollowDetailViewController.swift */; }; 0EFA3DDE25D3A03D0003C76B /* LoadingLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EFA3DDD25D3A03D0003C76B /* LoadingLabel.swift */; }; 0EFB4F222639790000530B5F /* ImageTitledStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EFB4F212639790000530B5F /* ImageTitledStack.swift */; }; @@ -651,6 +652,7 @@ 0E42905C263A742D008DA046 /* WaterfallGrid in Frameworks */, 0E429070263A8557008DA046 /* ImageScrollView in Frameworks */, 0E429067263A84CA008DA046 /* AppCenterAnalytics in Frameworks */, + 0EEA957B265FE11400689E78 /* Introspect in Frameworks */, 0E429065263A84CA008DA046 /* AppCenterCrashes in Frameworks */, 0E42906D263A853E008DA046 /* Connectivity in Frameworks */, ); @@ -1388,6 +1390,7 @@ 0E42906C263A853E008DA046 /* Connectivity */, 0E42906F263A8557008DA046 /* ImageScrollView */, 0E429072263A8572008DA046 /* Cache */, + 0EEA957A265FE11400689E78 /* Introspect */, ); productName = Hollow; productReference = 0E415A7025CD769B00351672 /* Hollow.app */; @@ -1481,6 +1484,7 @@ 0E42906B263A853E008DA046 /* XCRemoteSwiftPackageReference "Connectivity" */, 0E42906E263A8557008DA046 /* XCRemoteSwiftPackageReference "ImageScrollView" */, 0E429071263A8572008DA046 /* XCRemoteSwiftPackageReference "Cache" */, + 0EEA9579265FE11400689E78 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */, ); productRefGroup = 0E415A7125CD769B00351672 /* Products */; projectDirPath = ""; @@ -2048,7 +2052,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = Hollow/Hollow.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 54; + CURRENT_PROJECT_VERSION = 58; DEVELOPMENT_TEAM = C5UH93T368; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = Hollow/Info.plist; @@ -2074,7 +2078,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = Hollow/Hollow.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 54; + CURRENT_PROJECT_VERSION = 58; DEVELOPMENT_TEAM = C5UH93T368; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = Hollow/Info.plist; @@ -2099,7 +2103,7 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CODE_SIGN_ENTITLEMENTS = HollowWidget/HollowWidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 54; + CURRENT_PROJECT_VERSION = 58; DEVELOPMENT_TEAM = C5UH93T368; INFOPLIST_FILE = HollowWidget/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.1; @@ -2127,7 +2131,7 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CODE_SIGN_ENTITLEMENTS = HollowWidget/HollowWidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 54; + CURRENT_PROJECT_VERSION = 58; DEVELOPMENT_TEAM = C5UH93T368; INFOPLIST_FILE = HollowWidget/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 14.1; @@ -2306,6 +2310,14 @@ minimumVersion = 6.0.1; }; }; + 0EEA9579265FE11400689E78 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/siteline/SwiftUI-Introspect.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.1.3; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -2404,6 +2416,11 @@ package = 0E429060263A7568008DA046 /* XCRemoteSwiftPackageReference "Alamofire" */; productName = Alamofire; }; + 0EEA957A265FE11400689E78 /* Introspect */ = { + isa = XCSwiftPackageProductDependency; + package = 0EEA9579265FE11400689E78 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */; + productName = Introspect; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 0E415A6825CD769B00351672 /* Project object */; diff --git a/Source/Hollow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Source/Hollow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 5e5c9713..e2ed094c 100644 --- a/Source/Hollow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Source/Hollow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -73,6 +73,15 @@ "version": "1.8.1" } }, + { + "package": "Introspect", + "repositoryURL": "https://github.com/siteline/SwiftUI-Introspect.git", + "state": { + "branch": null, + "revision": "2e09be8af614401bc9f87d40093ec19ce56ccaf2", + "version": "0.1.3" + } + }, { "package": "WaterfallGrid", "repositoryURL": "https://github.com/paololeonardi/WaterfallGrid.git", diff --git a/Source/Hollow/App/AppDelegate.swift b/Source/Hollow/App/AppDelegate.swift index fe918f08..9073805e 100644 --- a/Source/Hollow/App/AppDelegate.swift +++ b/Source/Hollow/App/AppDelegate.swift @@ -15,8 +15,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { Defaults[.customColorSet] = Defaults[.tempCustomColorSet] Defaults[.applyCustomColorSet] = Defaults[.customColorSet] != nil setupApplication(application) - let appearance = UITableView.appearance(whenContainedInInstancesOf: [HollowDetailViewController.self, HollowDetailViewController_iPad.self]) - appearance.backgroundColor = UIColor(Color.hollowCardBackground) return true } diff --git a/Source/Hollow/View/Components/MyTextField.swift b/Source/Hollow/View/Components/MyTextField.swift index 1145360b..241e72b8 100644 --- a/Source/Hollow/View/Components/MyTextField.swift +++ b/Source/Hollow/View/Components/MyTextField.swift @@ -15,6 +15,7 @@ struct MyTextField: View where Content: View { var footer: String? = nil var isSecureContent = false var backgroundColor: Color = .hollowCardBackground + var disabled = false var content: (() -> Content)? = nil var body: some View { @@ -36,6 +37,8 @@ struct MyTextField: View where Content: View { .autocapitalization(.none) .disableAutocorrection(true) .dynamicFont(size: 16) + .foregroundColor(disabled ? .secondary : nil) + .disabled(disabled) Spacer() if let content = content { content() diff --git a/Source/Hollow/View/Components/SearchBar.swift b/Source/Hollow/View/Components/SearchBar.swift index 40f7b61c..62e58a89 100644 --- a/Source/Hollow/View/Components/SearchBar.swift +++ b/Source/Hollow/View/Components/SearchBar.swift @@ -14,7 +14,7 @@ struct SearchBar: View { var body: some View { Button(action:{ // Navigate to search view - withAnimation(.defaultSpring) { + withAnimation { isSearching = true } }) { diff --git a/Source/Hollow/View/Components/Toast.swift b/Source/Hollow/View/Components/Toast.swift index b77c6b85..eb626246 100644 --- a/Source/Hollow/View/Components/Toast.swift +++ b/Source/Hollow/View/Components/Toast.swift @@ -82,6 +82,7 @@ struct Toast: View { .lineSpacing(2) .lineLimit(4) } + .animation(.none) .foregroundColor(configuration.style.fontColor) .padding() .padding(.horizontal, 5) @@ -94,13 +95,11 @@ struct Toast: View { .opacity(opacity) .padding() .padding(.horizontal) - .animation(.default) - .transition(.move(edge: .bottom)) .onClickGesture(perform: configuration.onTap ?? dismiss) .onAppear { - withAnimation(.spring()) { + withAnimation(.easeInOut) { opacity = 1 } DispatchQueue.main.asyncAfter(deadline: .now() + 1.5, execute: dismiss) @@ -110,7 +109,7 @@ struct Toast: View { func dismiss() { guard presented else { return } - withAnimation(.spring()) { + withAnimation(.easeInOut) { self.opacity = 0 } DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) { diff --git a/Source/Hollow/View/Hierarchy/Account/SettingsSubViews.swift b/Source/Hollow/View/Hierarchy/Account/SettingsSubViews.swift index 633fea56..5baca389 100644 --- a/Source/Hollow/View/Hierarchy/Account/SettingsSubViews.swift +++ b/Source/Hollow/View/Hierarchy/Account/SettingsSubViews.swift @@ -497,8 +497,6 @@ struct OtherSettingsView: View { } private struct ExperimentalFeaturesView: View { - @Default(.reduceImageQuality) var reduceImageQuality - @Default(.useListInDetail) var useListInDetail var body: some View { List { @@ -506,31 +504,6 @@ struct OtherSettingsView: View { Text("SETTINGSVIEW_OTHER_EXP_FEAT_DESCRIPTION") } .padding(.vertical) - - Section( - footer: Text("SETTINGSVIEW_OTHER_EXP_REDUCE_IMG_QUALITY_FOOTER").padding(.horizontal)) { - HStack { - Text("SETTINGSVIEW_OTHER_EXP_REDUCE_IMG_QUALITY_LABEL") - Spacer() - - Toggle("", isOn: $reduceImageQuality) - .defaultToggleStyle() - } - - } - - #if !targetEnvironment(macCatalyst) - Section(footer: Text("SETTINGSVIEW_OTHER_EXP_FIX_SCROLL_FOOTER").padding(.horizontal)) { - HStack { - Text("SETTINGSVIEW_OTHER_EXP_FIX_SCROLL_LABEL") - Spacer() - - Toggle("", isOn: $useListInDetail) - .defaultToggleStyle() - } - - } - #endif } .defaultListStyle() diff --git a/Source/Hollow/View/Hierarchy/Hollow/Content/HollowImageView.swift b/Source/Hollow/View/Hierarchy/Hollow/Content/HollowImageView.swift index a51f244a..12ed91b5 100644 --- a/Source/Hollow/View/Hierarchy/Hollow/Content/HollowImageView.swift +++ b/Source/Hollow/View/Hierarchy/Hollow/Content/HollowImageView.swift @@ -36,7 +36,6 @@ struct HollowImageView: View { } @ScaledMetric private var reloadButtonSize: CGFloat = 50 - @Default(.reduceImageQuality) var reduceImageQuality var body: some View { Group { @@ -46,7 +45,7 @@ struct HollowImageView: View { if imageAspectRatio >= aspectRatio - 0.001 { Image(uiImage: image) .resizable() - .interpolation(reduceImageQuality ? .none : .low) + .interpolation(.low) .aspectRatio(contentMode: .fit) .imageSaver(image: image, showSavePhotoAlert: $showSavePhotoAlert, savePhotoError: $savePhotoError) } else { @@ -54,7 +53,7 @@ struct HollowImageView: View { Color.hollowCommentQuoteText.opacity(0.09).ignoresSafeArea() Image(uiImage: image) .resizable() - .interpolation(reduceImageQuality ? .none : .low) + .interpolation(.low) .aspectRatio(contentMode: .fit) .imageSaver(image: image, showSavePhotoAlert: $showSavePhotoAlert, savePhotoError: $savePhotoError) } @@ -63,7 +62,6 @@ struct HollowImageView: View { } } - .animation(.default) .contentShape(RoundedRectangle(cornerRadius: 4)) .onChange(of: showSavePhotoAlert) { show in if show { diff --git a/Source/Hollow/View/Hierarchy/Hollow/Content/HollowTextView.swift b/Source/Hollow/View/Hierarchy/Hollow/Content/HollowTextView.swift index 0c28e9b2..aec304b4 100644 --- a/Source/Hollow/View/Hierarchy/Hollow/Content/HollowTextView.swift +++ b/Source/Hollow/View/Hierarchy/Hollow/Content/HollowTextView.swift @@ -8,6 +8,7 @@ import SwiftUI import Defaults +import Introspect struct HollowTextView: View { var text: String @@ -56,12 +57,15 @@ struct HollowTextView: View { if highlight { Text.highlightLinksAndCitation(text, modifiers: { $0.underline() - .foregroundColor(.tint) + .foregroundColor(.hollowContentText) }) + } else { Text(text) + } } + .modifier(TextModifier(inDetail: inDetail, compactLineLimit: compactLineLimit)) } diff --git a/Source/Hollow/View/Hierarchy/Hollow/Detail/HollowDetailSubViews.swift b/Source/Hollow/View/Hierarchy/Hollow/Detail/HollowDetailSubViews.swift index 37dc20dd..48a05851 100644 --- a/Source/Hollow/View/Hierarchy/Hollow/Detail/HollowDetailSubViews.swift +++ b/Source/Hollow/View/Hierarchy/Hollow/Detail/HollowDetailSubViews.swift @@ -55,9 +55,10 @@ extension HollowDetailView { .background(Color.hollowCardBackground) .lineLimit(1) - ForEach(comments) { comment in + ForEach(comments, id: \.commentId) { comment in commentView(for: comment) .fixedSize(horizontal: false, vertical: true) + .id(comment.commentId) } if store.isLoading, postData.replyNumber > postData.comments.count { @@ -66,6 +67,7 @@ extension HollowDetailView { .padding(.horizontal) .padding(.top, postData.comments.isEmpty ? 0 : 15) .padding(.bottom, postData.comments.isEmpty ? 15 : 0) + .background(Color.hollowCardBackground) } } @@ -114,11 +116,7 @@ extension HollowDetailView { Group { highlighted ? Color.background : Color.hollowCardBackground } - .roundedCorner(highlighted ? 10 : 0) - .padding(.horizontal, highlighted ? 10 : 0) -// .transition(.opacity) ) - .contentShape(RoundedRectangle(cornerRadius: 10, style: .continuous)) .onClickGesture { guard !store.isSendingComment && !store.isLoading else { return } UIImpactFeedbackGenerator(style: .soft).impactOccurred() @@ -175,8 +173,6 @@ extension HollowDetailView { commentId: comment.commentId ) } - .id(comment.commentId) - }} } diff --git a/Source/Hollow/View/Hierarchy/Hollow/Detail/HollowDetailView.swift b/Source/Hollow/View/Hierarchy/Hollow/Detail/HollowDetailView.swift index 0dc9f2ee..3d2f84cf 100644 --- a/Source/Hollow/View/Hierarchy/Hollow/Detail/HollowDetailView.swift +++ b/Source/Hollow/View/Hierarchy/Hollow/Detail/HollowDetailView.swift @@ -7,6 +7,7 @@ import SwiftUI import Defaults +import Introspect struct HollowDetailView: View { @ObservedObject var store: HollowDetailStore @@ -17,11 +18,9 @@ struct HollowDetailView: View { @State var inputPresented = false @State var jumpedToCommentId: Int? @State var jumpedFromCommentId: Int? - @State private var showHeaderContent = Defaults[.useListInDetail] @State var reverseComments = false @State var showOnlyName: String? - private let scrollToAnchor = UnitPoint(x: 0.5, y: 0.1) let scrollAnimation = Animation.spring(response: 0.3) @ScaledMetric(wrappedValue: 10) var headerVerticalPadding: CGFloat @@ -33,8 +32,6 @@ struct HollowDetailView: View { @Namespace var buttonAnimationNamespace - @Default(.useListInDetail) var useListInDetail - var body: some View { VStack(spacing: 0) { if showHeader { @@ -90,65 +87,90 @@ struct HollowDetailView: View { } } - if useListInDetail { + ScrollViewReader { proxy in List { - content - .listRowInsets(EdgeInsets()) - .background(Color.hollowCardBackground) + VStack(spacing: 0) { + let spacing: CGFloat = UIDevice.isMac ? 20 : 13 + + Spacer().fixedSize() + .id(-1) + + if store.noSuchPost { + Text("DETAILVIEW_NO_SUCH_POST_PLACEHOLDER") + .padding(.top, spacing) + .padding(.horizontal) + .modifier(HollowTextView.TextModifier(inDetail: true)) + + } else { + HollowContentView( + postDataWrapper: store.postDataWrapper, + options: [.displayVote, .displayImage, .displayCitedPost, .revealFoldTags, .showHyperlinks], + voteHandler: store.vote, + imageReloadHandler: { _ in store.loadPostImage() } + ) + .padding(.top, spacing) + .padding(.horizontal) + .background(Color.hollowCardBackground) + } + + Spacer(minLength: spacing * 2).fixedSize() + + } + .listRowBackground(Color.hollowCardBackground) + .listRowInsets(EdgeInsets()) + .background(Color.hollowCardBackground) + .id(-1) + + if !store.noSuchPost { + commentView + .listRowInsets(EdgeInsets()) + } + } + .introspectTableView(customize: { $0.backgroundColor = nil }) + .background(Color.hollowCardBackground) + .coordinateSpace(name: "detail.scrollview") .buttonStyle(BorderlessButtonStyle()) - - } else { - ScrollView { ScrollViewReader { proxy in - LazyVStack(spacing: 0) { - content + .onChange(of: store.replyToIndex) { index in + guard index != -2 else { return } + let id = index >= 0 ? store.postDataWrapper.post.comments[index].commentId : -1 + withAnimation(scrollAnimation) { + proxy.scrollTo(id, anchor: .top) } - .padding([.horizontal, .bottom], UIDevice.isMac ? ViewConstants.macAdditionalPadding : 0) - .padding(.top, UIDevice.isMac ? 10 : 0) - .edgesIgnoringSafeArea(.bottom) - - .onChange(of: store.replyToIndex) { index in - guard index != -2 else { return } - let id = index >= 0 ? store.postDataWrapper.post.comments[index].commentId : -1 + } + .onChange(of: jumpedFromCommentId) { commentId in + if commentId != nil { withAnimation(scrollAnimation) { - proxy.scrollTo(id, anchor: scrollToAnchor) + jumpedFromCommentId = nil + proxy.scrollTo(commentId, anchor: .top) + jumpedToCommentId = commentId + } + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + guard self.jumpedToCommentId == commentId else { return } + withAnimation(scrollAnimation) { jumpedToCommentId = nil } } } - .onChange(of: jumpedFromCommentId) { commentId in - if commentId != nil { + } + // Jump to certain comment + .onChange(of: store.isLoading) { loading in + if !loading { + // Check if there is any comment to jump to + // when finish loading + if let jumpToCommentId = store.jumpToCommentId { withAnimation(scrollAnimation) { - jumpedFromCommentId = nil - proxy.scrollTo(commentId, anchor: scrollToAnchor) - jumpedToCommentId = commentId + proxy.scrollTo(jumpToCommentId, anchor: .top) + jumpedToCommentId = jumpToCommentId } DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - guard self.jumpedToCommentId == commentId else { return } - withAnimation(scrollAnimation) { jumpedToCommentId = nil } + guard self.jumpedToCommentId == jumpToCommentId else { return } + withAnimation(scrollAnimation) { + self.jumpedToCommentId = nil } } + store.jumpToCommentId = nil } } - // Jump to certain comment - .onChange(of: store.isLoading) { loading in - if !loading { - // Check if there is any comment to jump to - // when finish loading - if let jumpToCommentId = store.jumpToCommentId { - withAnimation(scrollAnimation) { - proxy.scrollTo(jumpToCommentId, anchor: scrollToAnchor) - jumpedToCommentId = jumpToCommentId - } - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - guard self.jumpedToCommentId == jumpToCommentId else { return } - withAnimation(scrollAnimation) { - self.jumpedToCommentId = nil } - } - store.jumpToCommentId = nil - } - } - } - - }} - .coordinateSpace(name: "detail.scrollview") + } + } } @@ -167,7 +189,7 @@ struct HollowDetailView: View { imageScaleFactor: 0.8, buttonAnimationNamespace: buttonAnimationNamespace ) -// .matchedGeometryEffect(id: "button", in: buttonAnimationNamespace) + // .matchedGeometryEffect(id: "button", in: buttonAnimationNamespace) .edgesIgnoringSafeArea(.bottom) .bottom() .trailing() @@ -213,54 +235,6 @@ struct HollowDetailView: View { } } -extension HollowDetailView { - - @ViewBuilder var content: some View { - - if useListInDetail { - VStack(spacing: 0) { - mainContent - } - } else { - mainContent - } - - if !store.noSuchPost { - commentView - .listRowInsets(EdgeInsets()) - } - } - - @ViewBuilder var mainContent: some View { - let spacing: CGFloat = UIDevice.isMac ? 20 : 13 - - Color.hollowCardBackground - .frame(height: 5) - .id(-1) - - if store.noSuchPost { - Text("DETAILVIEW_NO_SUCH_POST_PLACEHOLDER") - .padding(.top, spacing) - .padding(.horizontal) - .modifier(HollowTextView.TextModifier(inDetail: true)) - - } else { - HollowContentView( - postDataWrapper: store.postDataWrapper, - options: [.displayVote, .displayImage, .displayCitedPost, .revealFoldTags, .showHyperlinks], - voteHandler: store.vote, - imageReloadHandler: { _ in store.loadPostImage() } - ) - .padding(.top, spacing) - .padding(.horizontal) - .background(Color.hollowCardBackground) - } - - Color.hollowCardBackground - .frame(height: spacing * 2) - } -} - extension HollowDetailView { @ViewBuilder static func conditionalDetailView(store: HollowDetailStore, push: Bool = UIDevice.isPad) -> some View { if push { diff --git a/Source/Hollow/View/Hierarchy/Hollow/Input/HollowCommentInputView.swift b/Source/Hollow/View/Hierarchy/Hollow/Input/HollowCommentInputView.swift index 59506637..35c83d52 100644 --- a/Source/Hollow/View/Hierarchy/Hollow/Input/HollowCommentInputView.swift +++ b/Source/Hollow/View/Hierarchy/Hollow/Input/HollowCommentInputView.swift @@ -87,7 +87,6 @@ struct HollowCommentInputView: View { .conditionalMatchedGeometryEffect(id: "button", in: buttonAnimationNamespace) .shadow(radius: 12) ) -// .roundedCorner(12) .padding() .animation(transitionAnimation) diff --git a/Source/Hollow/View/Hierarchy/Login/LoginSubViews.swift b/Source/Hollow/View/Hierarchy/Login/LoginSubViews.swift index cd3a9fa1..04d36c5d 100644 --- a/Source/Hollow/View/Hierarchy/Login/LoginSubViews.swift +++ b/Source/Hollow/View/Hierarchy/Login/LoginSubViews.swift @@ -103,30 +103,45 @@ extension LoginView { struct EmailTextField: View { @EnvironmentObject var viewModel: LoginStore private let configuration = Defaults[.hollowConfig]! + var disabled: Bool { viewModel.emailCheckType == .oldUser } var body: some View { - MyTextField(text: $viewModel.email, - placeHolder: NSLocalizedString("LOGINVIEW_EMAIL_TEXTFIELD_PLACEHOLDER", comment: ""), - title: NSLocalizedString("LOGINVIEW_EMAIL_TEXTFIELD_TITLE", comment: "")) { - // Accessory view for selecting email suffix - Menu(content: { - ForEach(configuration.emailSuffixes.indices, id: \.self) { index in - Button(configuration.emailSuffixes[index], action: { - viewModel.emailSuffix = configuration.emailSuffixes[index] + HStack { + MyTextField(text: disabled ? .constant(viewModel.email + "@" + viewModel.emailSuffix) : $viewModel.email, + placeHolder: NSLocalizedString("LOGINVIEW_EMAIL_TEXTFIELD_PLACEHOLDER", comment: ""), + title: NSLocalizedString("LOGINVIEW_EMAIL_TEXTFIELD_TITLE", comment: ""), + disabled: viewModel.emailCheckType == .oldUser) { Group { + // Accessory view for selecting email suffix + if !disabled { + Menu(content: { + ForEach(configuration.emailSuffixes.indices, id: \.self) { index in + Button(configuration.emailSuffixes[index], action: { + viewModel.emailSuffix = configuration.emailSuffixes[index] + }) + } + }, label: { + HStack { + Text("@" + viewModel.emailSuffix) + Image(systemName: "chevron.down") + .layoutPriority(1) + } + .lineLimit(1) + .dynamicFont(size: 14) + .foregroundColor(.hollowContentText) + + }) + } else { + Button(action: { viewModel.restore(); viewModel.email = "" }) { + Image(systemName: "xmark.circle.fill") + } + .foregroundColor(.uiColor(.systemFill)) } - }, label: { - HStack { - Text("@" + viewModel.emailSuffix) - Image(systemName: "chevron.down") - .layoutPriority(1) - } - .lineLimit(1) - .dynamicFont(size: 14) - .foregroundColor(.hollowContentText) - }) + + }} + .keyboardType(.emailAddress) + } - .keyboardType(.emailAddress) } } diff --git a/Source/Hollow/View/Hierarchy/Login/WelcomeView.swift b/Source/Hollow/View/Hierarchy/Login/WelcomeView.swift index 0f3e701f..f74e8bc7 100644 --- a/Source/Hollow/View/Hierarchy/Login/WelcomeView.swift +++ b/Source/Hollow/View/Hierarchy/Login/WelcomeView.swift @@ -32,7 +32,7 @@ struct WelcomeView: View { .foregroundColor(Color("hollow.content.text.other")) if viewModel.isLoadingConfig { - Spinner(color: Color("hollow.content.text.other"), desiredWidth: 20) + Spinner(color: Color("hollow.content.text.other"), desiredWidth: 16) } } .padding(.top, 70) diff --git a/Source/Hollow/View/Hierarchy/Main/MainView.swift b/Source/Hollow/View/Hierarchy/Main/MainView.swift index ba648a38..b7e784a3 100644 --- a/Source/Hollow/View/Hierarchy/Main/MainView.swift +++ b/Source/Hollow/View/Hierarchy/Main/MainView.swift @@ -111,17 +111,18 @@ extension MainView { var body: some View { HStack(spacing: 2) { Group { - Button(action: { withAnimation { page = .wander }}) { + Button(action: { page = .wander }) { mainTabText(text: NSLocalizedString("GLOBAL_WANDER", comment: ""), selected: page == .wander) - .animation(.defaultSpring) + .animation(.spring()) } .disabled(page == .wander) mainTabText(text: "/", selected: true) .rotationEffect(.init(degrees: page == .wander ? 360 : 0)) - .animation(.defaultSpring) - Button(action: { withAnimation { page = .timeline }}) { + .animation(.spring()) + + Button(action: { page = .timeline }) { mainTabText(text: NSLocalizedString("GLOBAL_TIMELINE", comment: ""), selected: page == .timeline) - .animation(.defaultSpring) + .animation(.spring()) } .disabled(page == .timeline) } diff --git a/Source/Hollow/View/Hierarchy/Main/TimelineView.swift b/Source/Hollow/View/Hierarchy/Main/TimelineView.swift index 73c5c5de..288c91ff 100644 --- a/Source/Hollow/View/Hierarchy/Main/TimelineView.swift +++ b/Source/Hollow/View/Hierarchy/Main/TimelineView.swift @@ -60,22 +60,25 @@ struct TimelineView: View { if let announcement = hollowConfig?.announcement, announcement != hiddenAnnouncement { VStack(alignment: .leading) { - Label( - NSLocalizedString("TIMELINEVIEW_ANNOUCEMENT_CARD_TITLE", comment: ""), - systemImage: "megaphone" - ) + HStack { + Label( + NSLocalizedString("TIMELINEVIEW_ANNOUCEMENT_CARD_TITLE", comment: ""), + systemImage: "megaphone" + ) + .dynamicFont(size: 17, weight: .bold) + .foregroundColor(.hollowContentText) + .layoutPriority(1) + Spacer() + Button("TIMELINEVIEW_ANNOUNCEMENT_HIDE_BUTTON") { withAnimation { + hiddenAnnouncement = announcement + }} + .dynamicFont(size: 17, weight: .medium) + .accentColor(.tint) + } + .lineLimit(1) .padding(.bottom, 10) - .dynamicFont(size: 17, weight: .bold) - .foregroundColor(.hollowContentText) + HollowTextView(text: announcement, inDetail: true, highlight: true) - MyButton(action: { withAnimation { - hiddenAnnouncement = announcement - }}) { - Text("TIMELINEVIEW_ANNOUNCEMENT_HIDE_BUTTON") - .dynamicFont(size: ViewConstants.plainButtonFontSize, weight: .bold) - .foregroundColor(.white) - } - .trailing() } .padding(.all, cardPadding) .background(Color.hollowCardBackground) diff --git a/Source/Hollow/en.lproj/Localizable.strings b/Source/Hollow/en.lproj/Localizable.strings index 7ded653f..e963e5e6 100644 --- a/Source/Hollow/en.lproj/Localizable.strings +++ b/Source/Hollow/en.lproj/Localizable.strings @@ -631,10 +631,6 @@ "SETTINGSVIEW_OTHER_EXP_FEAT_DESCRIPTION" = "These are some experimental features that are not fully tested, so use them at your own risk. File a report if any error occurs."; -"SETTINGSVIEW_OTHER_EXP_REDUCE_IMG_QUALITY_FOOTER" = "Reduce the render quality in photo previews. Detailed image viewing are not affected."; - -"SETTINGSVIEW_OTHER_EXP_REDUCE_IMG_QUALITY_LABEL" = "Reduce Image Render Quality"; - "SETTINGSVIEW_APPEARANCE_AVATAR_HDR" = "Avatar"; "SETTINGSVIEW_APPEARANCE_GRAPHICAL_AVATAR_STYLE" = "Graphical"; @@ -667,10 +663,6 @@ "HOLLOWDETAIL_COMMENTS_ORDER_NEW_TO_OLD" = "New to Old"; -"SETTINGSVIEW_OTHER_EXP_FIX_SCROLL_LABEL" = "Fix Scrolling Issue in Detail View"; - -"SETTINGSVIEW_OTHER_EXP_FIX_SCROLL_FOOTER" = "Jump to certain comment is not supported in this mode."; - "COMMENT_VIEW_SHOW_ONLY_LABEL" = "Show this Person Only"; "WIDGET_DISPLAY_NAME" = "Trending"; diff --git a/Source/Hollow/zh-Hans.lproj/Localizable.strings b/Source/Hollow/zh-Hans.lproj/Localizable.strings index f564c71f..3168662b 100644 --- a/Source/Hollow/zh-Hans.lproj/Localizable.strings +++ b/Source/Hollow/zh-Hans.lproj/Localizable.strings @@ -632,10 +632,6 @@ "SETTINGSVIEW_OTHER_EXP_FEAT_DESCRIPTION" = "这是一些未经充分测试的实验性功能。若出现问题,请发送反馈。"; -"SETTINGSVIEW_OTHER_EXP_REDUCE_IMG_QUALITY_FOOTER" = "降低图片预览的渲染质量。图片查看不受影响。"; - -"SETTINGSVIEW_OTHER_EXP_REDUCE_IMG_QUALITY_LABEL" = "降低图片渲染质量"; - "SETTINGSVIEW_APPEARANCE_AVATAR_HDR" = "头像"; "SETTINGSVIEW_APPEARANCE_GRAPHICAL_AVATAR_STYLE" = "图像"; @@ -668,10 +664,6 @@ "HOLLOWDETAIL_COMMENTS_ORDER_NEW_TO_OLD" = "倒序"; -"SETTINGSVIEW_OTHER_EXP_FIX_SCROLL_LABEL" = "修复详情界面滑动问题"; - -"SETTINGSVIEW_OTHER_EXP_FIX_SCROLL_FOOTER" = "此模式打开时无法进行评论跳转。"; - "COMMENT_VIEW_SHOW_ONLY_LABEL" = "仅显示此人评论"; "WIDGET_DISPLAY_NAME" = "热榜"; diff --git a/Source/Shared/Model/Extensions/DefaultsKeys.swift b/Source/Shared/Model/Extensions/DefaultsKeys.swift index 3cf7501a..a1f916eb 100644 --- a/Source/Shared/Model/Extensions/DefaultsKeys.swift +++ b/Source/Shared/Model/Extensions/DefaultsKeys.swift @@ -86,8 +86,7 @@ extension Defaults.Keys { // MARK: - Experimental Features extension Defaults.Keys { - static let reduceImageQuality = Key("user.settings.reduce.image.quality", default: false) - static let useListInDetail = Key("user.settings.use.list.in.detail", default: false) + } #endif