mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Merge commit '6ece02e998ee2812e81c9166cae8f17d71ee643d'
This commit is contained in:
commit
1ea4088098
@ -338,15 +338,17 @@ final class DrawingSettings: Codable, Equatable {
|
||||
|
||||
private final class ReferenceContentSource: ContextReferenceContentSource {
|
||||
private let sourceView: UIView
|
||||
private let contentArea: CGRect
|
||||
private let customPosition: CGPoint
|
||||
|
||||
init(sourceView: UIView, customPosition: CGPoint) {
|
||||
init(sourceView: UIView, contentArea: CGRect, customPosition: CGPoint) {
|
||||
self.sourceView = sourceView
|
||||
self.contentArea = contentArea
|
||||
self.customPosition = customPosition
|
||||
}
|
||||
|
||||
func transitionInfo() -> ContextControllerReferenceViewInfo? {
|
||||
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds, customPosition: customPosition)
|
||||
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: self.contentArea, customPosition: customPosition)
|
||||
}
|
||||
}
|
||||
|
||||
@ -849,7 +851,7 @@ private final class DrawingScreenComponent: CombinedComponent {
|
||||
)
|
||||
]
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkPresentationTheme)
|
||||
let contextController = ContextController(account: self.context.account, presentationData: presentationData, source: .reference(ReferenceContentSource(sourceView: sourceView, customPosition: CGPoint(x: 7.0, y: 3.0))), items: .single(ContextController.Items(content: .list(items))))
|
||||
let contextController = ContextController(account: self.context.account, presentationData: presentationData, source: .reference(ReferenceContentSource(sourceView: sourceView, contentArea: UIScreen.main.bounds, customPosition: CGPoint(x: 7.0, y: 3.0))), items: .single(ContextController.Items(content: .list(items))))
|
||||
self.present(contextController)
|
||||
}
|
||||
|
||||
@ -2294,18 +2296,18 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController {
|
||||
|
||||
private weak var currentFontPicker: ContextController?
|
||||
func presentFontPicker(sourceView: UIView) {
|
||||
guard !self.dismissFontPicker() else {
|
||||
guard !self.dismissFontPicker(), let validLayout = self.validLayout?.0 else {
|
||||
return
|
||||
}
|
||||
let fonts: [DrawingTextFont] = [
|
||||
.sanFrancisco,
|
||||
.newYork,
|
||||
.other("MarkerFelt-Wide", "Marker Felt"),
|
||||
.other("Chalkduster", "Chalkduster"),
|
||||
.other("Menlo-Bold", "Menlo"),
|
||||
.other("Copperplate-Bold", "Copperplate"),
|
||||
.other("GillSans-SemiBold", "Gill Sans"),
|
||||
.other("Papyrus", "Papyrus")
|
||||
.other("AmericanTypewriter", "American Typewriter"),
|
||||
.other("AvenirNext-DemiBoldItalic", "Avenir Next"),
|
||||
.other("CourierNewPS-BoldMT", "Courier New"),
|
||||
.other("Noteworthy-Bold", "Noteworthy"),
|
||||
.other("Georgia-Bold", "Georgia"),
|
||||
.other("Papyrus", "Papyrus"),
|
||||
.other("SnellRoundhand-Bold", "Snell Roundhand")
|
||||
]
|
||||
|
||||
var items: [ContextMenuItem] = []
|
||||
@ -2325,7 +2327,7 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController {
|
||||
}
|
||||
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkPresentationTheme)
|
||||
let contextController = ContextController(account: self.context.account, presentationData: presentationData, source: .reference(ReferenceContentSource(sourceView: sourceView, customPosition: CGPoint(x: 7.0, y: 0.0))), items: .single(ContextController.Items(content: .list(items))))
|
||||
let contextController = ContextController(account: self.context.account, presentationData: presentationData, source: .reference(ReferenceContentSource(sourceView: sourceView, contentArea: CGRect(origin: .zero, size: CGSize(width: validLayout.size.width, height: validLayout.size.height - (validLayout.inputHeight ?? 0.0))), customPosition: CGPoint(x: 0.0, y: 1.0))), items: .single(ContextController.Items(content: .list(items))))
|
||||
self.controller?.present(contextController, in: .window(.root))
|
||||
self.currentFontPicker = contextController
|
||||
}
|
||||
|
@ -78,7 +78,6 @@ public final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
|
||||
enum Font: Codable {
|
||||
case sanFrancisco
|
||||
case newYork
|
||||
case other(String, String)
|
||||
}
|
||||
|
||||
@ -258,7 +257,7 @@ final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate {
|
||||
self.textView.minimumZoomScale = 1.0
|
||||
self.textView.maximumZoomScale = 1.0
|
||||
self.textView.keyboardAppearance = .dark
|
||||
self.textView.autocorrectionType = .default
|
||||
self.textView.autocorrectionType = .no
|
||||
self.textView.spellCheckingType = .no
|
||||
|
||||
super.init(context: context, entity: entity)
|
||||
@ -551,11 +550,9 @@ final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate {
|
||||
var font: UIFont
|
||||
switch self.textEntity.font {
|
||||
case .sanFrancisco:
|
||||
font = Font.with(size: fontSize, design: .regular, weight: .semibold)
|
||||
case .newYork:
|
||||
font = Font.with(size: fontSize, design: .serif, weight: .semibold)
|
||||
font = Font.with(size: fontSize, design: .round, weight: .semibold)
|
||||
case let .other(fontName, _):
|
||||
font = UIFont(name: fontName, size: fontSize) ?? Font.with(size: fontSize, design: .regular, weight: .semibold)
|
||||
font = UIFont(name: fontName, size: fontSize) ?? Font.with(size: fontSize, design: .round, weight: .semibold)
|
||||
}
|
||||
|
||||
text.addAttribute(.font, value: font, range: range)
|
||||
@ -1286,6 +1283,7 @@ private var availableFonts: [String: (String, String)] = {
|
||||
|
||||
var preferredFont: String?
|
||||
for name in names {
|
||||
print(name)
|
||||
let originalName = name
|
||||
let name = name.lowercased()
|
||||
if (!name.contains("-") || name.contains("regular")) && preferredFont == nil {
|
||||
@ -1301,6 +1299,6 @@ private var availableFonts: [String: (String, String)] = {
|
||||
result[shortname] = (preferredFont, family)
|
||||
}
|
||||
}
|
||||
print(result)
|
||||
//print(result)
|
||||
return result
|
||||
}()
|
||||
|
@ -996,7 +996,7 @@ private class DrawingSlice {
|
||||
self.rect = rect
|
||||
self.path = NSTemporaryDirectory() + "/drawing_\(uuid.hashValue).slice"
|
||||
|
||||
DrawingSlice.queue.async {
|
||||
DrawingSlice.queue.after(2.0) {
|
||||
let image = UIImage(cgImage: image)
|
||||
if let data = image.pngData() as? NSData {
|
||||
try? data.write(toFile: self.path)
|
||||
|
@ -198,7 +198,7 @@ final class PenTool: DrawingElement {
|
||||
let minRenderArrowLength = max(10.0, max(drawingSize.width, drawingSize.height) * 0.02)
|
||||
|
||||
self.renderLineWidth = lineWidth
|
||||
self.renderMinLineWidth = isEraser || isBlur ? lineWidth : minLineWidth + (lineWidth - minLineWidth) * 0.3
|
||||
self.renderMinLineWidth = isEraser || isBlur ? lineWidth : minLineWidth + (lineWidth - minLineWidth) * 0.2
|
||||
self.renderArrowLength = max(minRenderArrowLength, lineWidth * 3.0)
|
||||
self.renderArrowLineWidth = max(minLineWidth * 1.8, lineWidth * 0.75)
|
||||
|
||||
@ -234,14 +234,8 @@ final class PenTool: DrawingElement {
|
||||
guard case let .point(point) = path else {
|
||||
return
|
||||
}
|
||||
|
||||
let filterDistance: CGFloat
|
||||
if point.velocity > 1200.0 {
|
||||
filterDistance = 25.0
|
||||
} else {
|
||||
filterDistance = 15.0
|
||||
}
|
||||
|
||||
|
||||
let filterDistance: CGFloat = 20.0
|
||||
if let previousPoint, point.location.distance(to: previousPoint) < filterDistance, state == .changed, self.segments.count > 1 {
|
||||
return
|
||||
}
|
||||
@ -252,14 +246,13 @@ final class PenTool: DrawingElement {
|
||||
velocity = 1000.0
|
||||
}
|
||||
|
||||
var effectiveRenderLineWidth = max(self.renderMinLineWidth, min(self.renderLineWidth - (velocity / 150.0), self.renderLineWidth))
|
||||
var effectiveRenderLineWidth = max(self.renderMinLineWidth, min(self.renderLineWidth - (velocity / 100.0), self.renderLineWidth))
|
||||
if let previousRenderLineWidth = self.previousRenderLineWidth {
|
||||
effectiveRenderLineWidth = effectiveRenderLineWidth * 0.2 + previousRenderLineWidth * 0.8
|
||||
}
|
||||
self.previousRenderLineWidth = effectiveRenderLineWidth
|
||||
|
||||
let rect = append(point: Point(position: point.location, width: effectiveRenderLineWidth))
|
||||
|
||||
if let currentRenderView = self.currentRenderView as? RenderView, let rect = rect {
|
||||
currentRenderView.draw(element: self, rect: rect)
|
||||
}
|
||||
@ -461,7 +454,7 @@ final class PenTool: DrawingElement {
|
||||
|
||||
let segmentDistance: CGFloat = 6.0
|
||||
let distance = midPoint1.distance(to: midPoint2)
|
||||
let numberOfSegments = min(128, max(floor(distance / segmentDistance), 32))
|
||||
let numberOfSegments = min(48, max(floor(distance / segmentDistance), 24))
|
||||
|
||||
let step = 1.0 / numberOfSegments
|
||||
for t in stride(from: 0, to: 1, by: step) {
|
||||
|
@ -46,15 +46,12 @@ enum DrawingTextAlignment: Equatable {
|
||||
|
||||
enum DrawingTextFont: Equatable, Hashable {
|
||||
case sanFrancisco
|
||||
case newYork
|
||||
case other(String, String)
|
||||
|
||||
init(font: DrawingTextEntity.Font) {
|
||||
switch font {
|
||||
case .sanFrancisco:
|
||||
self = .sanFrancisco
|
||||
case .newYork:
|
||||
self = .newYork
|
||||
case let .other(font, name):
|
||||
self = .other(font, name)
|
||||
}
|
||||
@ -64,8 +61,6 @@ enum DrawingTextFont: Equatable, Hashable {
|
||||
switch self {
|
||||
case .sanFrancisco:
|
||||
return .sanFrancisco
|
||||
case .newYork:
|
||||
return .newYork
|
||||
case let .other(font, name):
|
||||
return .other(font, name)
|
||||
}
|
||||
@ -75,8 +70,6 @@ enum DrawingTextFont: Equatable, Hashable {
|
||||
switch self {
|
||||
case .sanFrancisco:
|
||||
return "San Francisco"
|
||||
case .newYork:
|
||||
return "New York"
|
||||
case let .other(_, name):
|
||||
return name
|
||||
}
|
||||
@ -85,9 +78,7 @@ enum DrawingTextFont: Equatable, Hashable {
|
||||
func uiFont(size: CGFloat) -> UIFont {
|
||||
switch self {
|
||||
case .sanFrancisco:
|
||||
return Font.semibold(size)
|
||||
case .newYork:
|
||||
return Font.with(size: size, design: .serif, weight: .semibold)
|
||||
return Font.with(size: size, design: .round, weight: .semibold)
|
||||
case let .other(font, _):
|
||||
return UIFont(name: font, size: size) ?? Font.semibold(size)
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ public final class StorageBox {
|
||||
let _ = try? FileManager.default.removeItem(atPath: databasePath)
|
||||
valueBox = SqliteValueBox(basePath: databasePath, queue: queue, isTemporary: false, isReadOnly: false, useCaches: true, removeDatabaseOnError: true, encryptionParameters: nil, upgradeProgress: { _ in })
|
||||
}
|
||||
guard let valueBox else {
|
||||
guard let valueBox = valueBox else {
|
||||
preconditionFailure("Could not open database")
|
||||
}
|
||||
self.valueBox = valueBox
|
||||
|
@ -40,7 +40,7 @@ public func requestUpdatesXml(account: Account, source: String) -> Signal<Data,
|
||||
|
||||
if let message = locallyRenderedMessage(message: storeMessage, peers: peers), let media = message.media.first as? TelegramMediaFile {
|
||||
return Signal { subscriber in
|
||||
let fetchDispsable = fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: MediaResourceReference.media(media: AnyMediaReference.message(message: MessageReference(message), media: media), resource: media.resource)).start()
|
||||
let fetchDispsable = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: MediaResourceReference.media(media: AnyMediaReference.message(message: MessageReference(message), media: media), resource: media.resource)).start()
|
||||
|
||||
let dataDisposable = account.postbox.mediaBox.resourceData(media.resource, option: .complete(waitUntilFetchStatus: true)).start(next: { data in
|
||||
if data.complete {
|
||||
@ -120,7 +120,7 @@ public func downloadAppUpdate(account: Account, source: String, messageId: Int32
|
||||
let removeDisposable = account.postbox.mediaBox.removeCachedResources([media.resource.id]).start(completed: {
|
||||
let reference = MediaResourceReference.media(media: .message(message: MessageReference(message), media: media), resource: media.resource)
|
||||
|
||||
fetchDisposable = fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: reference).start()
|
||||
fetchDisposable = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: reference).start()
|
||||
statusDisposable = account.postbox.mediaBox.resourceStatus(media.resource).start(next: { status in
|
||||
switch status {
|
||||
case let .Fetching(_, progress):
|
||||
|
@ -1379,7 +1379,7 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
||||
}))
|
||||
|
||||
let setText: String
|
||||
if user.photo.first?.isPersonal == true {
|
||||
if user.photo.first?.isPersonal == true || state.updatingAvatar != nil {
|
||||
setText = presentationData.strings.UserInfo_ChangeCustomPhoto(compactName).string
|
||||
} else {
|
||||
setText = presentationData.strings.UserInfo_SetCustomPhoto(compactName).string
|
||||
@ -3117,7 +3117,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
let firstName = strongSelf.headerNode.editingContentNode.editingTextForKey(.firstName) ?? ""
|
||||
let lastName = strongSelf.headerNode.editingContentNode.editingTextForKey(.lastName) ?? ""
|
||||
|
||||
if peer.firstName != firstName || peer.lastName != lastName {
|
||||
if (peer.firstName ?? "") != firstName || (peer.lastName ?? "") != lastName {
|
||||
if firstName.isEmpty && lastName.isEmpty {
|
||||
if strongSelf.hapticFeedback == nil {
|
||||
strongSelf.hapticFeedback = HapticFeedback()
|
||||
@ -7179,7 +7179,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
confirmationAction = nil
|
||||
}
|
||||
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasDeleteButton, hasViewButton: false, personalPhoto: strongSelf.isSettings, isVideo: currentIsVideo, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: isForum, title: title, isSuggesting: mode == .suggest)!
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasDeleteButton, hasViewButton: false, personalPhoto: strongSelf.isSettings, isVideo: currentIsVideo, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: isForum, title: title, isSuggesting: [.custom, .suggest].contains(mode))!
|
||||
mixin.stickersContext = paintStickersContext
|
||||
let _ = strongSelf.currentAvatarMixin.swap(mixin)
|
||||
mixin.requestSearchController = { [weak self] assetsController in
|
||||
|
@ -415,7 +415,9 @@ public final class OngoingGroupCallContext {
|
||||
private final class Impl {
|
||||
let queue: Queue
|
||||
let context: GroupCallThreadLocalContext
|
||||
#if os(iOS)
|
||||
let audioDevice: SharedCallAudioDevice?
|
||||
#endif
|
||||
let sessionId = UInt32.random(in: 0 ..< UInt32(Int32.max))
|
||||
|
||||
let joinPayload = Promise<(String, UInt32)>()
|
||||
@ -433,9 +435,10 @@ public final class OngoingGroupCallContext {
|
||||
init(queue: Queue, inputDeviceId: String, outputDeviceId: String, audioSessionActive: Signal<Bool, NoError>, video: OngoingCallVideoCapturer?, requestMediaChannelDescriptions: @escaping (Set<UInt32>, @escaping ([MediaChannelDescription]) -> Void) -> Disposable, rejoinNeeded: @escaping () -> Void, outgoingAudioBitrateKbit: Int32?, videoContentType: VideoContentType, enableNoiseSuppression: Bool, disableAudioInput: Bool, preferX264: Bool, logPath: String) {
|
||||
self.queue = queue
|
||||
|
||||
#if os(iOS)
|
||||
self.audioDevice = nil
|
||||
let audioDevice = self.audioDevice
|
||||
|
||||
#endif
|
||||
var networkStateUpdatedImpl: ((GroupCallNetworkState) -> Void)?
|
||||
var audioLevelsUpdatedImpl: (([NSNumber]) -> Void)?
|
||||
|
||||
@ -450,7 +453,7 @@ public final class OngoingGroupCallContext {
|
||||
}
|
||||
|
||||
var getBroadcastPartsSource: (() -> BroadcastPartSource?)?
|
||||
|
||||
#if os(iOS)
|
||||
self.context = GroupCallThreadLocalContext(
|
||||
queue: ContextQueueImpl(queue: queue),
|
||||
networkStateUpdated: { state in
|
||||
@ -544,6 +547,101 @@ public final class OngoingGroupCallContext {
|
||||
logPath: logPath,
|
||||
audioDevice: audioDevice
|
||||
)
|
||||
#else
|
||||
self.context = GroupCallThreadLocalContext(
|
||||
queue: ContextQueueImpl(queue: queue),
|
||||
networkStateUpdated: { state in
|
||||
networkStateUpdatedImpl?(state)
|
||||
},
|
||||
audioLevelsUpdated: { levels in
|
||||
audioLevelsUpdatedImpl?(levels)
|
||||
},
|
||||
inputDeviceId: inputDeviceId,
|
||||
outputDeviceId: outputDeviceId,
|
||||
videoCapturer: video?.impl,
|
||||
requestMediaChannelDescriptions: { ssrcs, completion in
|
||||
final class OngoingGroupCallMediaChannelDescriptionTaskImpl : NSObject, OngoingGroupCallMediaChannelDescriptionTask {
|
||||
private let disposable: Disposable
|
||||
|
||||
init(disposable: Disposable) {
|
||||
self.disposable = disposable
|
||||
}
|
||||
|
||||
func cancel() {
|
||||
self.disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
let disposable = requestMediaChannelDescriptions(Set(ssrcs.map { $0.uint32Value }), { channels in
|
||||
completion(channels.map { channel -> OngoingGroupCallMediaChannelDescription in
|
||||
let mappedType: OngoingGroupCallMediaChannelType
|
||||
switch channel.kind {
|
||||
case .audio:
|
||||
mappedType = .audio
|
||||
case .video:
|
||||
mappedType = .video
|
||||
}
|
||||
return OngoingGroupCallMediaChannelDescription(
|
||||
type: mappedType,
|
||||
audioSsrc: channel.audioSsrc,
|
||||
videoDescription: channel.videoDescription
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
return OngoingGroupCallMediaChannelDescriptionTaskImpl(disposable: disposable)
|
||||
},
|
||||
requestCurrentTime: { completion in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
queue.async {
|
||||
disposable.set(getBroadcastPartsSource?()?.requestTime(completion: completion))
|
||||
}
|
||||
|
||||
return OngoingGroupCallBroadcastPartTaskImpl(disposable: disposable)
|
||||
},
|
||||
requestAudioBroadcastPart: { timestampMilliseconds, durationMilliseconds, completion in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
queue.async {
|
||||
disposable.set(getBroadcastPartsSource?()?.requestPart(timestampMilliseconds: timestampMilliseconds, durationMilliseconds: durationMilliseconds, subject: .audio, completion: completion, rejoinNeeded: {
|
||||
rejoinNeeded()
|
||||
}))
|
||||
}
|
||||
|
||||
return OngoingGroupCallBroadcastPartTaskImpl(disposable: disposable)
|
||||
},
|
||||
requestVideoBroadcastPart: { timestampMilliseconds, durationMilliseconds, channelId, quality, completion in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
queue.async {
|
||||
let mappedQuality: OngoingGroupCallContext.VideoChannel.Quality
|
||||
switch quality {
|
||||
case .thumbnail:
|
||||
mappedQuality = .thumbnail
|
||||
case .medium:
|
||||
mappedQuality = .medium
|
||||
case .full:
|
||||
mappedQuality = .full
|
||||
@unknown default:
|
||||
mappedQuality = .thumbnail
|
||||
}
|
||||
disposable.set(getBroadcastPartsSource?()?.requestPart(timestampMilliseconds: timestampMilliseconds, durationMilliseconds: durationMilliseconds, subject: .video(channelId: channelId, quality: mappedQuality), completion: completion, rejoinNeeded: {
|
||||
rejoinNeeded()
|
||||
}))
|
||||
}
|
||||
|
||||
return OngoingGroupCallBroadcastPartTaskImpl(disposable: disposable)
|
||||
},
|
||||
outgoingAudioBitrateKbit: outgoingAudioBitrateKbit ?? 32,
|
||||
videoContentType: _videoContentType,
|
||||
enableNoiseSuppression: enableNoiseSuppression,
|
||||
disableAudioInput: disableAudioInput,
|
||||
preferX264: preferX264,
|
||||
logPath: logPath
|
||||
)
|
||||
#endif
|
||||
|
||||
|
||||
let queue = self.queue
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user