Various improvements

This commit is contained in:
Ilya Laktyushin 2024-08-08 23:47:25 +02:00
parent aa3296cf95
commit 0dc4ce81f9
7 changed files with 198 additions and 158 deletions

View File

@ -12711,5 +12711,13 @@ Sorry for the inconvenience.";
"Stars.Transaction.Subscription.Renewed.Title" = "Subscription renewed";
"Stars.Transaction.Subscription.Renewed.Text" = "You renewed your subscription to [%1$@]().";
"Stars.Intro.Subscriptions.Title" = "MY SUBSCRIPTIONS";
"Stars.Intro.Subscriptions.PerMonth" = "per month";
"Stars.Intro.Subscriptions.Renews" = "renews on %@";
"Stars.Intro.Subscriptions.Expires" = "expires on %@";
"Stars.Intro.Subscriptions.Expired" = "expired on %@";
"Stars.Intro.Subscriptions.Cancelled" = "cancelled";
"Stars.Intro.Subscriptions.ShowMore" = "Show More";
"Stars.Intro.Transaction.SubscriptionFee.Title" = "Monthly Subscription Fee";
"Stars.Intro.Transaction.Reaction.Title" = "Star Reaction";

View File

@ -54,10 +54,7 @@ final class BrowserPdfContent: UIView, BrowserContent, WKNavigationDelegate, WKU
self.presentationData = presentationData
self.webView = PDFView()
self.webView.maxScaleFactor = 4.0;
self.webView.minScaleFactor = self.webView.scaleFactorForSizeToFit
self.webView.autoScales = true
var scrollView: UIScrollView?
for view in self.webView.subviews {
if let view = view as? UIScrollView {
@ -72,16 +69,11 @@ final class BrowserPdfContent: UIView, BrowserContent, WKNavigationDelegate, WKU
}
self.scrollView = scrollView
self.webView.displayDirection = .vertical
self.webView.autoScales = true
var title: String = "file"
if let path = self.context.account.postbox.mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe) {
// var updatedPath = path
// if let fileName = file.fileName {
// let tempFile = TempBox.shared.file(path: path, fileName: fileName)
// updatedPath = tempFile.path
// self.tempFile = tempFile
// title = fileName
// }
self.webView.document = PDFDocument(data: data)
title = file.fileName ?? "file"
}
@ -96,9 +88,11 @@ final class BrowserPdfContent: UIView, BrowserContent, WKNavigationDelegate, WKU
}
self.addSubview(self.webView)
Queue.mainQueue().after(1.0) {
scrollView?.delegate = self
}
// Queue.mainQueue().after(1.0) {
// if let scrollView = self.scrollView {
// scrollView.delegate = self
// }
// }
}
required init?(coder: NSCoder) {
@ -251,42 +245,20 @@ final class BrowserPdfContent: UIView, BrowserContent, WKNavigationDelegate, WKU
private var validLayout: (CGSize, UIEdgeInsets, UIEdgeInsets)?
func updateLayout(size: CGSize, insets: UIEdgeInsets, fullInsets: UIEdgeInsets, safeInsets: UIEdgeInsets, transition: ComponentTransition) {
let isFirstTime = self.validLayout == nil
self.validLayout = (size, insets, fullInsets)
self.previousScrollingOffset = ScrollingOffsetState(value: self.scrollView.contentOffset.y, isDraggingOrDecelerating: self.scrollView.isDragging || self.scrollView.isDecelerating)
let webViewFrame = CGRect(origin: CGPoint(x: insets.left, y: insets.top), size: CGSize(width: size.width - insets.left - insets.right, height: size.height - insets.top - insets.bottom))
var refresh = false
if self.webView.frame.width > 0 && webViewFrame.width != self.webView.frame.width {
refresh = true
}
transition.setFrame(view: self.webView, frame: webViewFrame)
if refresh {
self.webView.reloadInputViews()
if isFirstTime {
self.webView.setNeedsLayout()
self.webView.layoutIfNeeded()
self.webView.minScaleFactor = self.webView.scaleFactorForSizeToFit
}
// if let error = self.currentError {
// let errorSize = self.errorView.update(
// transition: .immediate,
// component: AnyComponent(
// ErrorComponent(
// theme: self.presentationData.theme,
// title: self.presentationData.strings.Browser_ErrorTitle,
// text: error.localizedDescription
// )
// ),
// environment: {},
// containerSize: CGSize(width: size.width - insets.left - insets.right - 72.0, height: size.height)
// )
// if self.errorView.superview == nil {
// self.addSubview(self.errorView)
// self.errorView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
// }
// self.errorView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - errorSize.width) / 2.0), y: insets.top + floorToScreenPixels((size.height - insets.top - insets.bottom - errorSize.height) / 2.0)), size: errorSize)
// } else if self.errorView.superview != nil {
// self.errorView.removeFromSuperview()
// }
}
private func updateState(_ f: (BrowserContentState) -> BrowserContentState) {
@ -302,22 +274,46 @@ final class BrowserPdfContent: UIView, BrowserContent, WKNavigationDelegate, WKU
private var previousScrollingOffset: ScrollingOffsetState?
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.updateScrollingOffset(isReset: false, transition: .immediate)
}
private func snapScrollingOffsetToInsets() {
let transition = ComponentTransition(animation: .curve(duration: 0.4, curve: .spring))
self.updateScrollingOffset(isReset: false, transition: transition)
}
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
if let scrollViewDelegate = scrollView as? UIScrollViewDelegate {
scrollViewDelegate.scrollViewWillBeginZooming?(scrollView, with: view)
}
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
if let scrollViewDelegate = scrollView as? UIScrollViewDelegate {
scrollViewDelegate.scrollViewDidEndZooming?(scrollView, with: view, atScale: scale)
}
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
if let scrollViewDelegate = scrollView as? UIScrollViewDelegate {
scrollViewDelegate.scrollViewDidZoom?(scrollView)
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.updateScrollingOffset(isReset: false, transition: .immediate)
}
public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if let scrollViewDelegate = scrollView as? UIScrollViewDelegate {
scrollViewDelegate.scrollViewDidEndDragging?(scrollView, willDecelerate: decelerate)
}
if !decelerate {
self.snapScrollingOffsetToInsets()
}
}
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if let scrollViewDelegate = scrollView as? UIScrollViewDelegate {
scrollViewDelegate.scrollViewDidEndDecelerating?(scrollView)
}
self.snapScrollingOffsetToInsets()
}

View File

@ -359,6 +359,7 @@ private final class BrowserScreenComponent: CombinedComponent {
canGoBack: context.component.contentState?.canGoBack ?? false,
canGoForward: context.component.contentState?.canGoForward ?? false,
canOpenIn: canOpenIn,
isDocument: context.component.contentState?.contentType == .document,
performAction: performAction,
performHoldAction: performHoldAction
)
@ -1090,16 +1091,19 @@ public class BrowserScreen: ViewController, MinimizableController {
var items: [ContextMenuItem] = []
items.append(.custom(fontItem, false))
if contentState.contentType == .document, contentState.title.lowercased().hasSuffix(".pdf") {
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.InstantPage_FontSanFrancisco, icon: forceIsSerif ? emptyIcon : checkIcon, action: { (controller, action) in
} else {
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.InstantPage_FontSanFrancisco, icon: forceIsSerif ? emptyIcon : checkIcon, action: { (controller, action) in
performAction.invoke(.updateFontIsSerif(false))
action(.default)
})))
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.InstantPage_FontNewYork, textFont: .custom(font: Font.with(size: 17.0, design: .serif, traits: []), height: nil, verticalOffset: nil), icon: forceIsSerif ? checkIcon : emptyIcon, action: { (controller, action) in
})))
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.InstantPage_FontNewYork, textFont: .custom(font: Font.with(size: 17.0, design: .serif, traits: []), height: nil, verticalOffset: nil), icon: forceIsSerif ? checkIcon : emptyIcon, action: { (controller, action) in
performAction.invoke(.updateFontIsSerif(true))
action(.default)
})))
})))
}
items.append(.separator)
@ -1383,15 +1387,15 @@ public class BrowserScreen: ViewController, MinimizableController {
private var validLayout: ContainerViewLayout?
public static let supportedDocumentMimeTypes: [String] = [
// "text/plain",
// "text/rtf",
// "application/pdf",
// "application/msword",
// "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
// "application/vnd.ms-excel",
// "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
// "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
// "application/vnd.openxmlformats-officedocument.presentationml.presentation"
"text/plain",
"text/rtf",
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
]
public init(context: AccountContext, subject: Subject, preferredConfiguration: WKWebViewConfiguration? = nil, openPreviousOnClose: Bool = false) {

View File

@ -125,6 +125,7 @@ final class NavigationToolbarContentComponent: CombinedComponent {
let canGoBack: Bool
let canGoForward: Bool
let canOpenIn: Bool
let isDocument: Bool
let performAction: ActionSlot<BrowserScreen.Action>
let performHoldAction: (UIView, ContextGesture?, BrowserScreen.Action) -> Void
@ -134,6 +135,7 @@ final class NavigationToolbarContentComponent: CombinedComponent {
canGoBack: Bool,
canGoForward: Bool,
canOpenIn: Bool,
isDocument: Bool,
performAction: ActionSlot<BrowserScreen.Action>,
performHoldAction: @escaping (UIView, ContextGesture?, BrowserScreen.Action) -> Void
) {
@ -142,6 +144,7 @@ final class NavigationToolbarContentComponent: CombinedComponent {
self.canGoBack = canGoBack
self.canGoForward = canGoForward
self.canOpenIn = canOpenIn
self.isDocument = isDocument
self.performAction = performAction
self.performHoldAction = performHoldAction
}
@ -162,6 +165,9 @@ final class NavigationToolbarContentComponent: CombinedComponent {
if lhs.canOpenIn != rhs.canOpenIn {
return false
}
if lhs.isDocument != rhs.isDocument {
return false
}
return true
}
@ -187,62 +193,6 @@ final class NavigationToolbarContentComponent: CombinedComponent {
let spacing = (availableSize.width - buttonSize.width * CGFloat(buttonCount) - sideInset * 2.0) / CGFloat(buttonCount - 1)
let canGoBack = context.component.canGoBack
let back = back.update(
component: ContextReferenceButtonComponent(
content: AnyComponent(
BundleIconComponent(
name: "Instant View/Back",
tintColor: canGoBack ? context.component.accentColor : context.component.accentColor.withAlphaComponent(0.4)
)
),
minSize: buttonSize,
action: { view, gesture in
guard canGoBack else {
return
}
if let gesture {
performHoldAction(view, gesture, .navigateBack)
} else {
performAction.invoke(.navigateBack)
}
}
),
availableSize: buttonSize,
transition: .easeInOut(duration: 0.2)
)
context.add(back
.position(CGPoint(x: sideInset + back.size.width / 2.0, y: availableSize.height / 2.0))
)
let canGoForward = context.component.canGoForward
let forward = forward.update(
component: ContextReferenceButtonComponent(
content: AnyComponent(
BundleIconComponent(
name: "Instant View/Forward",
tintColor: canGoForward ? context.component.accentColor : context.component.accentColor.withAlphaComponent(0.4)
)
),
minSize: buttonSize,
action: { view, gesture in
guard canGoForward else {
return
}
if let gesture {
performHoldAction(view, gesture, .navigateForward)
} else {
performAction.invoke(.navigateForward)
}
}
),
availableSize: buttonSize,
transition: .easeInOut(duration: 0.2)
)
context.add(forward
.position(CGPoint(x: sideInset + back.size.width + spacing + forward.size.width / 2.0, y: availableSize.height / 2.0))
)
let share = share.update(
component: Button(
content: AnyComponent(
@ -258,48 +208,111 @@ final class NavigationToolbarContentComponent: CombinedComponent {
availableSize: buttonSize,
transition: .easeInOut(duration: 0.2)
)
context.add(share
.position(CGPoint(x: sideInset + back.size.width + spacing + forward.size.width + spacing + share.size.width / 2.0, y: availableSize.height / 2.0))
)
let bookmark = bookmark.update(
component: Button(
content: AnyComponent(
BundleIconComponent(
name: "Instant View/Bookmark",
tintColor: context.component.accentColor
)
if context.component.isDocument {
context.add(share
.position(CGPoint(x: sideInset + share.size.width / 2.0, y: availableSize.height / 2.0))
)
} else {
let canGoBack = context.component.canGoBack
let back = back.update(
component: ContextReferenceButtonComponent(
content: AnyComponent(
BundleIconComponent(
name: "Instant View/Back",
tintColor: canGoBack ? context.component.accentColor : context.component.accentColor.withAlphaComponent(0.4)
)
),
minSize: buttonSize,
action: { view, gesture in
guard canGoBack else {
return
}
if let gesture {
performHoldAction(view, gesture, .navigateBack)
} else {
performAction.invoke(.navigateBack)
}
}
),
action: {
performAction.invoke(.openBookmarks)
}
).minSize(buttonSize),
availableSize: buttonSize,
transition: .easeInOut(duration: 0.2)
)
context.add(bookmark
.position(CGPoint(x: sideInset + back.size.width + spacing + forward.size.width + spacing + share.size.width + spacing + bookmark.size.width / 2.0, y: availableSize.height / 2.0))
)
if context.component.canOpenIn {
let openIn = openIn.update(
availableSize: buttonSize,
transition: .easeInOut(duration: 0.2)
)
context.add(back
.position(CGPoint(x: sideInset + back.size.width / 2.0, y: availableSize.height / 2.0))
)
let canGoForward = context.component.canGoForward
let forward = forward.update(
component: ContextReferenceButtonComponent(
content: AnyComponent(
BundleIconComponent(
name: "Instant View/Forward",
tintColor: canGoForward ? context.component.accentColor : context.component.accentColor.withAlphaComponent(0.4)
)
),
minSize: buttonSize,
action: { view, gesture in
guard canGoForward else {
return
}
if let gesture {
performHoldAction(view, gesture, .navigateForward)
} else {
performAction.invoke(.navigateForward)
}
}
),
availableSize: buttonSize,
transition: .easeInOut(duration: 0.2)
)
context.add(forward
.position(CGPoint(x: sideInset + back.size.width + spacing + forward.size.width / 2.0, y: availableSize.height / 2.0))
)
context.add(share
.position(CGPoint(x: sideInset + back.size.width + spacing + forward.size.width + spacing + share.size.width / 2.0, y: availableSize.height / 2.0))
)
let bookmark = bookmark.update(
component: Button(
content: AnyComponent(
BundleIconComponent(
name: "Instant View/Browser",
name: "Instant View/Bookmark",
tintColor: context.component.accentColor
)
),
action: {
performAction.invoke(.openIn)
performAction.invoke(.openBookmarks)
}
).minSize(buttonSize),
availableSize: buttonSize,
transition: .easeInOut(duration: 0.2)
)
context.add(openIn
.position(CGPoint(x: sideInset + back.size.width + spacing + forward.size.width + spacing + share.size.width + spacing + bookmark.size.width + spacing + openIn.size.width / 2.0, y: availableSize.height / 2.0))
context.add(bookmark
.position(CGPoint(x: sideInset + back.size.width + spacing + forward.size.width + spacing + share.size.width + spacing + bookmark.size.width / 2.0, y: availableSize.height / 2.0))
)
if context.component.canOpenIn {
let openIn = openIn.update(
component: Button(
content: AnyComponent(
BundleIconComponent(
name: "Instant View/Browser",
tintColor: context.component.accentColor
)
),
action: {
performAction.invoke(.openIn)
}
).minSize(buttonSize),
availableSize: buttonSize,
transition: .easeInOut(duration: 0.2)
)
context.add(openIn
.position(CGPoint(x: sideInset + back.size.width + spacing + forward.size.width + spacing + share.size.width + spacing + bookmark.size.width + spacing + openIn.size.width / 2.0, y: availableSize.height / 2.0))
)
}
}
return availableSize

View File

@ -363,7 +363,6 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
}
}
var currentFontState = BrowserPresentationState.FontState(size: 100, isSerif: false)
func updateFontState(_ state: BrowserPresentationState.FontState) {
self.updateFontState(state, force: false)

View File

@ -22,6 +22,8 @@ import ListActionItemComponent
import StarsAvatarComponent
import TelegramStringFormatting
private let initialSubscriptionsDisplayedLimit: Int32 = 3
final class StarsTransactionsScreenComponent: Component {
typealias EnvironmentType = ViewControllerComponentContainer.Environment
@ -127,6 +129,8 @@ final class StarsTransactionsScreenComponent: Component {
private var subscriptionsStateDisposable: Disposable?
private var subscriptionsState: StarsSubscriptionsContext.State?
private var subscriptionsExpanded = false
private var subscriptionsMoreDisplayed: Int32 = 0
private var allTransactionsContext: StarsTransactionsContext?
private var incomingTransactionsContext: StarsTransactionsContext?
@ -601,7 +605,16 @@ final class StarsTransactionsScreenComponent: Component {
let fontBaseDisplaySize = 17.0
var subscriptionsItems: [AnyComponentWithIdentity<Empty>] = []
if let subscriptionsState = self.subscriptionsState {
for subscription in subscriptionsState.subscriptions {
var subscriptions = subscriptionsState.subscriptions
var limit: Int32
if self.subscriptionsExpanded {
limit = 25 + self.subscriptionsMoreDisplayed
} else {
limit = initialSubscriptionsDisplayedLimit
}
subscriptions = Array(subscriptions.prefix(Int(limit)))
for subscription in subscriptions {
var titleComponents: [AnyComponentWithIdentity<Empty>] = []
titleComponents.append(
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
@ -618,12 +631,12 @@ final class StarsTransactionsScreenComponent: Component {
let dateValue = stringForDateWithoutYear(date: Date(timeIntervalSince1970: Double(subscription.untilDate)), strings: environment.strings)
if subscription.flags.contains(.isCancelled) {
if subscription.untilDate > Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) {
dateText = "expires on \(dateValue)"
dateText = environment.strings.Stars_Intro_Subscriptions_Expires(dateValue).string
} else {
dateText = "expired on \(dateValue)"
dateText = environment.strings.Stars_Intro_Subscriptions_Expired(dateValue).string
}
} else {
dateText = "renews on \(dateValue)"
dateText = environment.strings.Stars_Intro_Subscriptions_Renews(dateValue).string
}
titleComponents.append(
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
@ -635,15 +648,14 @@ final class StarsTransactionsScreenComponent: Component {
maximumNumberOfLines: 1
)))
)
let labelComponent: AnyComponentWithIdentity<Empty>
if subscription.flags.contains(.isCancelled) {
labelComponent = AnyComponentWithIdentity(id: "cancelledLabel", component: AnyComponent(
MultilineTextComponent(text: .plain(NSAttributedString(string: "cancelled", font: Font.regular(floor(fontBaseDisplaySize * 13.0 / 17.0)), textColor: environment.theme.list.itemDestructiveColor)))
MultilineTextComponent(text: .plain(NSAttributedString(string: environment.strings.Stars_Intro_Subscriptions_Cancelled, font: Font.regular(floor(fontBaseDisplaySize * 13.0 / 17.0)), textColor: environment.theme.list.itemDestructiveColor)))
))
} else {
let itemLabel = NSAttributedString(string: "\(subscription.pricing.amount)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemPrimaryTextColor)
let itemSublabel = NSAttributedString(string: "per month", font: Font.regular(floor(fontBaseDisplaySize * 13.0 / 17.0)), textColor: environment.theme.list.itemSecondaryTextColor)
let itemSublabel = NSAttributedString(string: environment.strings.Stars_Intro_Subscriptions_PerMonth, font: Font.regular(floor(fontBaseDisplaySize * 13.0 / 17.0)), textColor: environment.theme.list.itemSecondaryTextColor)
labelComponent = AnyComponentWithIdentity(id: "label", component: AnyComponent(StarsLabelComponent(text: itemLabel, subtext: itemSublabel)))
}
@ -675,7 +687,7 @@ final class StarsTransactionsScreenComponent: Component {
ListActionItemComponent(
theme: environment.theme,
title: AnyComponent(Text(
text: "Show More",
text: environment.strings.Stars_Intro_Subscriptions_ShowMore,
font: Font.regular(17.0),
color: environment.theme.list.itemAccentColor
)),
@ -690,8 +702,16 @@ final class StarsTransactionsScreenComponent: Component {
false
),
accessory: nil,
action: { _ in
action: { [weak self] _ in
guard let self, let component = self.component else {
return
}
if self.subscriptionsExpanded {
self.subscriptionsMoreDisplayed += 10
} else {
self.subscriptionsExpanded = true
}
component.subscriptionsContext.loadMore()
},
highlighting: .default,
updateIsHighlighted: { view, _ in
@ -703,14 +723,13 @@ final class StarsTransactionsScreenComponent: Component {
}
if !subscriptionsItems.isEmpty {
//TODO:localize
let subscriptionsSize = self.subscriptionsView.update(
transition: .immediate,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
header: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: "My Subscriptions".uppercased(),
string: environment.strings.Stars_Intro_Subscriptions_Title.uppercased(),
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
)),
@ -1049,6 +1068,7 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
}
self.starsContext.load(force: false)
self.subscriptionsContext.loadMore()
}
required public init(coder aDecoder: NSCoder) {

View File

@ -231,7 +231,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
params.present(controller, nil)
} else if let rootController = params.navigationController?.view.window?.rootViewController {
let proceed = {
if params.context.sharedContext.immediateExperimentalUISettings.browserExperiment && BrowserScreen.supportedDocumentMimeTypes.contains(file.mimeType) {
if BrowserScreen.supportedDocumentMimeTypes.contains(file.mimeType) {
let subject: BrowserScreen.Subject
if file.mimeType == "application/pdf" {
subject = .pdfDocument(file: file)