Various fixes

This commit is contained in:
Ilya Laktyushin 2024-07-26 12:26:37 +02:00
parent c5179bc4a6
commit cd810b940a
12 changed files with 337 additions and 85 deletions

View File

@ -12585,6 +12585,9 @@ Sorry for the inconvenience.";
"WebBrowser.Exceptions.ClearConfirmation.Text" = "Are you sure you want to clear this list?";
"WebBrowser.Exceptions.ClearConfirmation.Clear" = "Clear";
"WebBrowser.ClearCookies.ClearConfirmation.Text" = "Are you sure you want to clear cookies?";
"WebBrowser.ClearCookies.ClearConfirmation.Clear" = "Clear";
"WebBrowser.Done" = "Done";
"AccessDenied.LocationWeather" = "Telegram needs access to your location so that you can add the weather widget to your stories.\n\nPlease go to Settings > Privacy > Location Services and set Telegram to ON.";
@ -12649,3 +12652,6 @@ Sorry for the inconvenience.";
"Story.Cover" = "Story Cover";
"Story.SaveCover" = "Save Cover";
"WebBrowser.DeleteBookmark" = "Delete Bookmark";
"WebBrowser.RemoveRecent" = "Remove from Recent";

View File

@ -8,26 +8,36 @@ import Postbox
import TelegramCore
import AccountContext
import TelegramPresentationData
import ContextUI
final class BrowserAddressListComponent: Component {
let context: AccountContext
let theme: PresentationTheme
let strings: PresentationStrings
let insets: UIEdgeInsets
let navigateTo: (String) -> Void
let metrics: LayoutMetrics
let addressBarFrame: CGRect
let performAction: ActionSlot<BrowserScreen.Action>
let presentInGlobalOverlay: (ViewController) -> Void
init(
context: AccountContext,
theme: PresentationTheme,
strings: PresentationStrings,
insets: UIEdgeInsets,
navigateTo: @escaping (String) -> Void
metrics: LayoutMetrics,
addressBarFrame: CGRect,
performAction: ActionSlot<BrowserScreen.Action>,
presentInGlobalOverlay: @escaping (ViewController) -> Void
) {
self.context = context
self.theme = theme
self.strings = strings
self.insets = insets
self.navigateTo = navigateTo
self.metrics = metrics
self.addressBarFrame = addressBarFrame
self.performAction = performAction
self.presentInGlobalOverlay = presentInGlobalOverlay
}
static func ==(lhs: BrowserAddressListComponent, rhs: BrowserAddressListComponent) -> Bool {
@ -43,6 +53,12 @@ final class BrowserAddressListComponent: Component {
if lhs.insets != rhs.insets {
return false
}
if lhs.metrics != rhs.metrics {
return false
}
if lhs.addressBarFrame != rhs.addressBarFrame {
return false
}
return true
}
@ -109,6 +125,8 @@ final class BrowserAddressListComponent: Component {
let bookmarks: [Message]
}
private let outerView = UIButton()
private let shadowView = UIImageView()
private let backgroundView = UIView()
private let scrollView = ScrollView()
private let itemContainerView = UIView()
@ -130,13 +148,19 @@ final class BrowserAddressListComponent: Component {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundView.clipsToBounds = true
self.scrollView.alwaysBounceVertical = true
self.scrollView.delegate = self
self.scrollView.showsVerticalScrollIndicator = false
self.addSubview(self.outerView)
self.addSubview(self.shadowView)
self.addSubview(self.backgroundView)
self.addSubview(self.scrollView)
self.backgroundView.addSubview(self.scrollView)
self.scrollView.addSubview(self.itemContainerView)
self.outerView.addTarget(self, action: #selector(self.outerPressed), for: .touchUpInside)
}
required init?(coder: NSCoder) {
@ -147,6 +171,10 @@ final class BrowserAddressListComponent: Component {
self.stateDisposable?.dispose()
}
@objc private func outerPressed() {
self.component?.performAction.invoke(.closeAddressBar)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if !self.ignoreScrolling {
self.updateScrolling(transition: .immediate)
@ -155,6 +183,8 @@ final class BrowserAddressListComponent: Component {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.window?.endEditing(true)
cancelContextGestures(view: scrollView)
}
private func updateScrolling(transition: ComponentTransition) {
@ -230,7 +260,7 @@ final class BrowserAddressListComponent: Component {
)
if let sectionHeaderView = sectionHeader.view {
if sectionHeaderView.superview == nil {
self.addSubview(sectionHeaderView)
self.backgroundView.addSubview(sectionHeaderView)
if !transition.animation.isImmediate {
sectionHeaderView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
@ -289,7 +319,7 @@ final class BrowserAddressListComponent: Component {
}
}
let navigateTo = component.navigateTo
let performAction = component.performAction
let _ = visibleItem.update(
transition: itemTransition,
component: AnyComponent(
@ -302,8 +332,49 @@ final class BrowserAddressListComponent: Component {
insets: component.insets,
action: {
if let url = webPage?.content.url {
navigateTo(url)
performAction.invoke(.navigateTo(url))
}
},
contextAction: { [weak self] webPage, message, sourceView, gesture in
guard let self, let component = self.component else {
return
}
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
var itemList: [ContextMenuItem] = []
if let message {
itemList.append(.action(ContextMenuActionItem(text: presentationData.strings.WebBrowser_DeleteBookmark, textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, f in
f(.dismissWithoutContent)
if let self, let component = self.component {
let _ = component.context.engine.messages.deleteMessagesInteractively(messageIds: [message.id], type: .forEveryone).startStandalone()
}
})))
} else {
itemList.append(.action(ContextMenuActionItem(text: presentationData.strings.WebBrowser_RemoveRecent, textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, f in
f(.dismissWithoutContent)
if let self, let component = self.component, let url = webPage.content.url {
let _ = removeRecentlyVisitedLink(engine: component.context.engine, url: url).startStandalone()
}
})))
}
let items = ContextController.Items(content: .list(itemList))
let controller = ContextController(
presentationData: presentationData,
source: .extracted(BrowserAddressListContextExtractedContentSource(contentView: sourceView)),
items: .single(items),
recognizer: nil,
gesture: gesture
)
component.presentInGlobalOverlay(controller)
})
),
environment: {},
@ -387,7 +458,22 @@ final class BrowserAddressListComponent: Component {
self.component = component
self.state = state
let resetScrolling = self.scrollView.bounds.width != availableSize.width
self.outerView.isHidden = !component.metrics.isTablet
self.outerView.frame = CGRect(origin: .zero, size: availableSize)
let containerFrame: CGRect
if component.metrics.isTablet {
let containerSize = CGSize(width: component.addressBarFrame.width + 32.0, height: 540.0)
containerFrame = CGRect(origin: CGPoint(x: floor(component.addressBarFrame.center.x - containerSize.width / 2.0), y: 72.0), size: containerSize)
self.backgroundView.layer.cornerRadius = 10.0
} else {
containerFrame = CGRect(origin: .zero, size: availableSize)
self.backgroundView.layer.cornerRadius = 0.0
}
let resetScrolling = self.scrollView.bounds.width != containerFrame.width
if themeUpdated {
self.backgroundView.backgroundColor = component.theme.list.plainBackgroundColor
}
@ -402,16 +488,13 @@ final class BrowserAddressListComponent: Component {
message: nil,
hasNext: true,
insets: .zero,
action: {}
action: {},
contextAction: nil
)),
environment: {},
containerSize: CGSize(width: itemsContainerWidth, height: 1000.0)
)
let _ = resetScrolling
let _ = addressItemSize
var sections: [ItemLayout.Section] = []
if let state = self.stateValue {
if !state.recent.isEmpty {
@ -432,37 +515,50 @@ final class BrowserAddressListComponent: Component {
}
}
let itemLayout = ItemLayout(containerSize: availableSize, insets: .zero, sections: sections)
let itemLayout = ItemLayout(containerSize: containerFrame.size, insets: .zero, sections: sections)
self.itemLayout = itemLayout
let containerWidth = availableSize.width
let scrollContentHeight = max(itemLayout.contentHeight, availableSize.height)
let containerWidth = containerFrame.size.width
let scrollContentHeight = max(itemLayout.contentHeight, containerFrame.size.height)
self.ignoreScrolling = true
transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: containerWidth, height: availableSize.height)))
transition.setFrame(view: self.scrollView, frame: CGRect(origin: .zero, size: containerFrame.size))
let contentSize = CGSize(width: containerWidth, height: scrollContentHeight)
if contentSize != self.scrollView.contentSize {
self.scrollView.contentSize = contentSize
}
// let contentInset: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: bottomPanelHeight + bottomPanelInset, right: 0.0)
// let indicatorInset = UIEdgeInsets(top: max(itemLayout.containerInset, environment.safeInsets.top + navigationHeight), left: 0.0, bottom: contentInset.bottom, right: 0.0)
// if indicatorInset != self.scrollView.scrollIndicatorInsets {
// self.scrollView.scrollIndicatorInsets = indicatorInset
// }
// if contentInset != self.scrollView.contentInset {
// self.scrollView.contentInset = contentInset
// }
if resetScrolling {
self.scrollView.bounds = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: containerWidth, height: availableSize.height))
self.scrollView.bounds = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: containerWidth, height: containerFrame.size.height))
}
self.ignoreScrolling = false
self.updateScrolling(transition: transition)
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: .zero, size: availableSize))
transition.setFrame(view: self.backgroundView, frame: containerFrame)
transition.setFrame(view: self.itemContainerView, frame: CGRect(origin: .zero, size: CGSize(width: containerWidth, height: scrollContentHeight)))
if component.metrics.isTablet {
transition.setFrame(view: self.shadowView, frame: containerFrame.insetBy(dx: -60.0, dy: -60.0))
self.shadowView.isHidden = false
if self.shadowView.image == nil {
self.shadowView.image = generateShadowImage()
}
} else {
self.shadowView.isHidden = true
}
return availableSize
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let result = super.hitTest(point, with: event)
if let component = self.component, component.metrics.isTablet {
let addressFrame = CGRect(origin: CGPoint(x: self.backgroundView.frame.minX, y: self.backgroundView.frame.minY - 48.0), size: CGSize(width: self.backgroundView.frame.width, height: 48.0))
if addressFrame.contains(point) {
return nil
}
}
return result
}
}
func makeView() -> View {
@ -473,3 +569,55 @@ final class BrowserAddressListComponent: Component {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}
private func generateShadowImage() -> UIImage? {
return generateImage(CGSize(width: 140.0, height: 140.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.saveGState()
context.setShadow(offset: CGSize(), blur: 60.0, color: UIColor(white: 0.0, alpha: 0.4).cgColor)
let path = UIBezierPath(roundedRect: CGRect(x: 60.0, y: 60.0, width: 20.0, height: 20.0), cornerRadius: 10.0).cgPath
context.addPath(path)
context.fillPath()
context.restoreGState()
context.setBlendMode(.clear)
context.addPath(path)
context.fillPath()
})?.stretchableImage(withLeftCapWidth: 70, topCapHeight: 70)
}
private final class BrowserAddressListContextExtractedContentSource: ContextExtractedContentSource {
let keepInPlace: Bool = false
let ignoreContentTouches: Bool = false
let blurBackground: Bool = true
private let contentView: ContextExtractedContentContainingView
init(contentView: ContextExtractedContentContainingView) {
self.contentView = contentView
}
func takeView() -> ContextControllerTakeViewInfo? {
return ContextControllerTakeViewInfo(containingItem: .view(self.contentView), contentAreaInScreenSpace: UIScreen.main.bounds)
}
func putBack() -> ContextControllerPutBackViewInfo? {
return ContextControllerPutBackViewInfo(contentAreaInScreenSpace: UIScreen.main.bounds)
}
}
private func cancelContextGestures(view: UIView) {
if let gestureRecognizers = view.gestureRecognizers {
for gesture in gestureRecognizers {
if let gesture = gesture as? ContextGesture {
gesture.cancel()
}
}
}
for subview in view.subviews {
cancelContextGestures(view: subview)
}
}

View File

@ -9,6 +9,7 @@ import MultilineTextComponent
import TelegramPresentationData
import PhotoResources
import AccountContext
import ContextUI
private let iconFont = Font.with(size: 30.0, design: .round, weight: .bold)
private let iconTextBackgroundImage = generateStretchableFilledCircleImage(radius: 6.0, color: UIColor(rgb: 0xFF9500))
@ -21,6 +22,7 @@ final class BrowserAddressListItemComponent: Component {
let hasNext: Bool
let insets: UIEdgeInsets
let action: () -> Void
let contextAction: ((TelegramMediaWebpage, Message?, ContextExtractedContentContainingView, ContextGesture) -> Void)?
init(
context: AccountContext,
@ -29,7 +31,8 @@ final class BrowserAddressListItemComponent: Component {
message: Message?,
hasNext: Bool,
insets: UIEdgeInsets,
action: @escaping () -> Void
action: @escaping () -> Void,
contextAction: ((TelegramMediaWebpage, Message?, ContextExtractedContentContainingView, ContextGesture) -> Void)?
) {
self.context = context
self.theme = theme
@ -38,6 +41,7 @@ final class BrowserAddressListItemComponent: Component {
self.hasNext = hasNext
self.insets = insets
self.action = action
self.contextAction = contextAction
}
static func ==(lhs: BrowserAddressListItemComponent, rhs: BrowserAddressListItemComponent) -> Bool {
@ -56,16 +60,19 @@ final class BrowserAddressListItemComponent: Component {
return true
}
final class View: UIView {
private let containerButton: HighlightTrackingButton
final class View: ContextControllerSourceView {
private let extractedContainerView = ContextExtractedContentContainingView()
private let containerButton = HighlightTrackingButton()
private let separatorLayer = SimpleLayer()
private var highlightedBackgroundLayer = SimpleLayer()
private var emptyIcon: UIImageView?
private var emptyLabel: ComponentView<Empty>?
private var icon = TransformImageNode()
private let title = ComponentView<Empty>()
private let subtitle = ComponentView<Empty>()
private let separatorLayer: SimpleLayer
private var isExtractedToContextMenu: Bool = false
private var component: BrowserAddressListItemComponent?
private weak var state: EmptyComponentState?
@ -73,16 +80,64 @@ final class BrowserAddressListItemComponent: Component {
private var currentIconImageRepresentation: TelegramMediaImageRepresentation?
override init(frame: CGRect) {
self.separatorLayer = SimpleLayer()
self.containerButton = HighlightTrackingButton()
super.init(frame: frame)
self.addSubview(self.extractedContainerView)
self.targetViewForActivationProgress = self.extractedContainerView.contentView
self.highlightedBackgroundLayer.opacity = 0.0
self.layer.addSublayer(self.separatorLayer)
self.addSubview(self.containerButton)
self.layer.addSublayer(self.highlightedBackgroundLayer)
self.extractedContainerView.contentView.addSubview(self.containerButton)
self.containerButton.addTarget(self, action: #selector(self.pressed), for: .touchUpInside)
self.containerButton.highligthedChanged = { [weak self] highlighted in
guard let self else {
return
}
if highlighted {
self.superview?.bringSubviewToFront(self)
self.highlightedBackgroundLayer.removeAnimation(forKey: "opacity")
self.highlightedBackgroundLayer.opacity = 1.0
} else {
self.highlightedBackgroundLayer.opacity = 0.0
self.highlightedBackgroundLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
}
}
self.extractedContainerView.isExtractedToContextPreviewUpdated = { [weak self] value in
guard let self, let component = self.component else {
return
}
self.containerButton.clipsToBounds = value
self.containerButton.backgroundColor = value ? component.theme.list.plainBackgroundColor : nil
self.containerButton.layer.cornerRadius = value ? 10.0 : 0.0
}
self.extractedContainerView.willUpdateIsExtractedToContextPreview = { [weak self] value, transition in
guard let self else {
return
}
self.isExtractedToContextMenu = value
let mappedTransition: ComponentTransition
if value {
mappedTransition = ComponentTransition(transition)
} else {
mappedTransition = ComponentTransition(animation: .curve(duration: 0.2, curve: .easeInOut))
}
self.state?.updated(transition: mappedTransition)
}
self.activated = { [weak self] gesture, _ in
guard let self, let component = self.component else {
gesture.cancel()
return
}
component.contextAction?(component.webPage, component.message, self.extractedContainerView, gesture)
}
}
required init?(coder: NSCoder) {
@ -282,14 +337,22 @@ final class BrowserAddressListItemComponent: Component {
}
if themeUpdated {
self.highlightedBackgroundLayer.backgroundColor = component.theme.list.itemHighlightedBackgroundColor.cgColor
self.separatorLayer.backgroundColor = component.theme.list.itemPlainSeparatorColor.cgColor
}
transition.setFrame(layer: self.highlightedBackgroundLayer, frame: CGRect(origin: .zero, size: CGSize(width: availableSize.width, height: height + UIScreenPixel)))
transition.setFrame(layer: self.separatorLayer, frame: CGRect(origin: CGPoint(x: leftInset, y: height), size: CGSize(width: availableSize.width - leftInset, height: UIScreenPixel)))
self.separatorLayer.isHidden = !component.hasNext
let containerFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: height))
transition.setFrame(view: self.containerButton, frame: containerFrame)
transition.setFrame(view: self.extractedContainerView, frame: containerFrame)
transition.setFrame(view: self.extractedContainerView.contentView, frame: containerFrame)
self.extractedContainerView.contentRect = containerFrame
self.isGestureEnabled = component.contextAction != nil
return CGSize(width: availableSize.width, height: height)
}
}

View File

@ -21,6 +21,14 @@ final class BrowserNavigationBarEnvironment: Equatable {
}
final class BrowserNavigationBarComponent: CombinedComponent {
public class ExternalState {
public fileprivate(set) var centerItemFrame: CGRect
public init() {
self.centerItemFrame = .zero
}
}
let backgroundColor: UIColor
let separatorColor: UIColor
let textColor: UIColor
@ -30,6 +38,7 @@ final class BrowserNavigationBarComponent: CombinedComponent {
let height: CGFloat
let sideInset: CGFloat
let metrics: LayoutMetrics
let externalState: ExternalState?
let leftItems: [AnyComponentWithIdentity<Empty>]
let rightItems: [AnyComponentWithIdentity<Empty>]
let centerItem: AnyComponentWithIdentity<BrowserNavigationBarEnvironment>?
@ -48,6 +57,7 @@ final class BrowserNavigationBarComponent: CombinedComponent {
height: CGFloat,
sideInset: CGFloat,
metrics: LayoutMetrics,
externalState: ExternalState?,
leftItems: [AnyComponentWithIdentity<Empty>],
rightItems: [AnyComponentWithIdentity<Empty>],
centerItem: AnyComponentWithIdentity<BrowserNavigationBarEnvironment>?,
@ -65,6 +75,7 @@ final class BrowserNavigationBarComponent: CombinedComponent {
self.height = height
self.sideInset = sideInset
self.metrics = metrics
self.externalState = externalState
self.leftItems = leftItems
self.rightItems = rightItems
self.centerItem = centerItem
@ -135,14 +146,14 @@ final class BrowserNavigationBarComponent: CombinedComponent {
return { context in
var availableWidth = context.availableSize.width
let sideInset: CGFloat = 16.0 + context.component.sideInset
let sideInset: CGFloat = (context.component.metrics.isTablet ? 20.0 : 16.0) + context.component.sideInset
let collapsedHeight: CGFloat = 24.0
let expandedHeight = context.component.height
let contentHeight: CGFloat = expandedHeight * (1.0 - context.component.collapseFraction) + collapsedHeight * context.component.collapseFraction
let size = CGSize(width: context.availableSize.width, height: context.component.topInset + contentHeight)
let verticalOffset: CGFloat = context.component.metrics.isTablet ? -3.0 : 0.0
let itemSpacing: CGFloat = context.component.metrics.isTablet ? 24.0 : 8.0
let verticalOffset: CGFloat = context.component.metrics.isTablet ? -2.0 : 0.0
let itemSpacing: CGFloat = context.component.metrics.isTablet ? 26.0 : 8.0
let background = background.update(
component: Rectangle(color: context.component.backgroundColor.withAlphaComponent(1.0)),
@ -268,12 +279,15 @@ final class BrowserNavigationBarComponent: CombinedComponent {
centerX = centerLeftInset + (context.availableSize.width - centerLeftInset - centerRightInset) / 2.0
}
if let centerItem = centerItem {
let centerItemPosition = CGPoint(x: centerX, y: context.component.topInset + contentHeight / 2.0 + verticalOffset)
context.add(centerItem
.position(CGPoint(x: centerX, y: context.component.topInset + contentHeight / 2.0 + verticalOffset))
.position(centerItemPosition)
.scale(1.0 - 0.35 * context.component.collapseFraction)
.appear(.default(scale: false, alpha: true))
.disappear(.default(scale: false, alpha: true))
)
context.component.externalState?.centerItemFrame = centerItem.size.centered(around: centerItemPosition)
}
if context.component.collapseFraction == 1.0 {

View File

@ -75,6 +75,8 @@ private final class BrowserScreenComponent: CombinedComponent {
let toolbar = Child(BrowserToolbarComponent.self)
let addressList = Child(BrowserAddressListComponent.self)
let navigationBarExternalState = BrowserNavigationBarComponent.ExternalState()
return { context in
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
let performAction = context.component.performAction
@ -311,6 +313,7 @@ private final class BrowserScreenComponent: CombinedComponent {
height: environment.navigationHeight - environment.statusBarHeight,
sideInset: environment.safeInsets.left,
metrics: environment.metrics,
externalState: navigationBarExternalState,
leftItems: navigationLeftItems,
rightItems: navigationRightItems,
centerItem: navigationContent,
@ -401,18 +404,22 @@ private final class BrowserScreenComponent: CombinedComponent {
if context.component.presentationState.addressFocused {
let addressListSize: CGSize
if isTablet {
addressListSize = CGSize(width: 660.0, height: 420.0)
addressListSize = context.availableSize
} else {
addressListSize = CGSize(width: context.availableSize.width, height: context.availableSize.height - navigationBar.size.height - toolbarSize)
}
let controller = environment.controller
let addressList = addressList.update(
component: BrowserAddressListComponent(
context: context.component.context,
theme: environment.theme,
strings: environment.strings,
insets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left, bottom: 0.0, right: environment.safeInsets.right),
navigateTo: { url in
performAction.invoke(.navigateTo(url))
metrics: environment.metrics,
addressBarFrame: navigationBarExternalState.centerItemFrame,
performAction: performAction,
presentInGlobalOverlay: { c in
controller()?.presentInGlobalOverlay(c)
}
),
availableSize: addressListSize,
@ -421,9 +428,7 @@ private final class BrowserScreenComponent: CombinedComponent {
if isTablet {
context.add(addressList
.position(CGPoint(x: context.availableSize.width / 2.0, y: navigationBar.size.height + addressList.size.height / 2.0 - 3.0))
.cornerRadius(10.0)
.clipsToBounds(true)
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
.appear(.default(alpha: true))
.disappear(.default(alpha: true))
)

View File

@ -353,24 +353,26 @@ public final class DeviceAccess {
} else {
completion(true)
}
} else if [.restricted, .denied].contains(status), let presentationData = presentationData {
let text: String
if case .restricted = status {
text = presentationData.strings.AccessDenied_CameraRestricted
} else {
switch cameraSubject {
case .video:
text = presentationData.strings.AccessDenied_Camera
case .videoCall:
text = presentationData.strings.AccessDenied_VideoCallCamera
case .qrCode:
text = presentationData.strings.AccessDenied_QrCamera
}
}
} else if [.restricted, .denied].contains(status) {
completion(false)
present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
openSettings()
})]), nil)
if let presentationData = presentationData {
let text: String
if case .restricted = status {
text = presentationData.strings.AccessDenied_CameraRestricted
} else {
switch cameraSubject {
case .video:
text = presentationData.strings.AccessDenied_Camera
case .videoCall:
text = presentationData.strings.AccessDenied_VideoCallCamera
case .qrCode:
text = presentationData.strings.AccessDenied_QrCamera
}
}
present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
openSettings()
})]), nil)
}
} else if case .authorized = status {
completion(true)
} else {

View File

@ -310,21 +310,35 @@ public func webBrowserSettingsController(context: AccountContext) -> ViewControl
let controller = ItemListController(context: context, state: signal)
clearCookiesImpl = { [weak controller] in
WKWebsiteDataStore.default().removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), modifiedSince: Date(timeIntervalSince1970: 0), completionHandler:{})
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
controller?.present(UndoOverlayController(
presentationData: presentationData,
content: .info(
title: nil,
text: presentationData.strings.WebBrowser_ClearCookies_Succeed,
timeout: nil,
customUndoText: nil
),
elevatedLayout: false,
position: .bottom,
action: { _ in return false }), in: .current
let alertController = textAlertController(
context: context,
updatedPresentationData: nil,
title: nil,
text: presentationData.strings.WebBrowser_ClearCookies_ClearConfirmation_Text,
actions: [
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}),
TextAlertAction(type: .defaultAction, title: presentationData.strings.WebBrowser_ClearCookies_ClearConfirmation_Clear, action: {
WKWebsiteDataStore.default().removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), modifiedSince: Date(timeIntervalSince1970: 0), completionHandler:{})
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
controller?.present(UndoOverlayController(
presentationData: presentationData,
content: .info(
title: nil,
text: presentationData.strings.WebBrowser_ClearCookies_Succeed,
timeout: nil,
customUndoText: nil
),
elevatedLayout: false,
position: .bottom,
action: { _ in return false }), in: .current
)
})
]
)
controller?.present(alertController, in: .window(.root))
}
addExceptionImpl = { [weak controller] in

View File

@ -1124,9 +1124,8 @@ public final class MediaEditor {
self.initialSeekPosition = position
return
}
if play {
self.renderer.setRate(1.0)
} else {
self.renderer.setRate(1.0)
if !play {
self.player?.pause()
self.additionalPlayer?.pause()
self.audioPlayer?.pause()

View File

@ -431,9 +431,6 @@ final class MediaCoverScreen: ViewController {
}
func animateOutToEditor(completion: @escaping () -> Void) {
self.controller?.withMediaEditor { mediaEditor in
mediaEditor.play()
}
if let view = self.componentHost.view as? MediaCoverScreenComponent.View {
view.animateOutToEditor(completion: completion)
}

View File

@ -46,7 +46,7 @@ extension MediaEditorScreen {
return true
}
func saveDraft(id: Int64?) {
func saveDraft(id: Int64?, edit: Bool = false) {
guard let subject = self.node.subject, let actualSubject = self.node.actualSubject, let mediaEditor = self.node.mediaEditor else {
return
}
@ -83,7 +83,9 @@ extension MediaEditorScreen {
}
if let resultImage = mediaEditor.resultImage {
mediaEditor.seek(0.0, andPlay: false)
if !edit {
mediaEditor.seek(0.0, andPlay: false)
}
makeEditorImageComposition(context: self.node.ciContext, postbox: self.context.account.postbox, inputImage: resultImage, dimensions: storyDimensions, values: values, time: .zero, textScale: 2.0, completion: { resultImage in
guard let resultImage else {
return

View File

@ -6492,6 +6492,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
}
if self.isEmbeddedEditor && !(hasAnyChanges || hasEntityChanges) {
self.saveDraft(id: randomId, edit: true)
self.completion(MediaEditorScreen.Result(media: nil, mediaAreas: [], caption: caption, coverTimestamp: mediaEditor.values.coverImageTimestamp, options: self.state.privacy, stickers: stickers, randomId: randomId), { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
self?.dismiss()

View File

@ -2919,7 +2919,7 @@ final class ShareWithPeersScreenComponent: Component {
contentTransition.setFrame(view: self.itemContainerView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: containerWidth, height: itemLayout.contentHeight + footersTotalHeight)))
let scrollContentHeight = max(topInset + itemLayout.contentHeight + containerInset, availableSize.height - containerInset)
let scrollContentHeight = max(topInset + itemLayout.contentHeight + containerInset + bottomPanelHeight, availableSize.height - containerInset)
transition.setFrame(view: self.scrollContentView, frame: CGRect(origin: CGPoint(x: 0.0, y: topInset + containerInset), size: CGSize(width: containerWidth, height: itemLayout.contentHeight)))